#JavaEE @alextheedom
Professional Java EE Design
PatternsAlex Theedom
@alextheedom
alextheedom.com
@alextheedom#JavaEE
Speaker’s Bio
•Senior Java Developer
•Author: Professional Java EE Design Patterns
•E-learning Platforms
•Cash Machine Software
•Microservice Based Lottery Systems
•Spring and Java EE
@alextheedom#JavaEE
What to expect
•What’s the story
•Why am I here? What’s the message?
•Whistle stop tour
•Design Patterns: what, when and why
•Context Dependency Injection
@alextheedom#JavaEE
What to expect
•Deep Dive
•Singleton Pattern
•Factory Pattern
•Harnessing the power (something special)
•Quickie Patterns
•Façade, Decorator, Observer
•Q&A
@alextheedom#JavaEE
What’s the story
•Java EE changed design pattern implementation
•Implementation has simplified
•Implementation has been enhanced
•Greater creativity
•How?
•I will show you today
•Change is part of Java EE continued development
@alextheedom#JavaEE
Design patterns: 3W’S
•What are design patterns?
•Why do we need them?
•When to use them?
@alextheedom#JavaEE
Context Dependency Injection
•Simplifies programming model
•Annotations have replaced XML config files
•Convention over Configuration
•Resources are injected by type
•@Inject and disambiguation @Qualifier
•POJO (JSR 299 managed bean)
•Otherwise @Producer
@alextheedom#JavaEE
Singleton Pattern
•Ubiquitous and controversial but inescapable
•Instantiated once
•Not normally destroy during application life cycle
@alextheedom#JavaEE
Conventional Implementation
public class Logger {
private static Logger instance;
private Logger() {
// Creation code here
}
public static synchronized Logger getInstance() {
if(instance == null) {
instance = new Logger();
}
return instance;
}
}
public class Logger {
private static Logger instance;
private Logger() {
// Creation code here
}
public static synchronized Logger getInstance() {
if(instance == null) {
instance = new Logger();
}
return instance;
}
}
@alextheedom#JavaEE
Conventional Implementation
•Only one instance of Logger created
•Created by first call the getInstance()
•Thread safe creation
•Use it like so:
Logger logger = Logger.getInstance();Logger logger = Logger.getInstance();
@alextheedom#JavaEE
Java EE Implementation
@Singleton
public class Logger {
private Logger() {
// Creation code here
}
}
@Singleton
public class Logger {
private Logger() {
// Creation code here
}
}
@alextheedom#JavaEE
Java EE Implementation
•Only one instance of Logger created
•Created by container (lazily)
•Knows it’s a singleton because @Singleton
•Use it like so:
@Inject
Logger logger;
@Inject
Logger logger;
@alextheedom#JavaEE
Java EE Implementation
•Eager instantiation @Startup
•Perform startup tasks @PostConstruct
@alextheedom#JavaEE
Java EE Implementation
@Startup
@Singleton
public class Logger {
private Logger() {
// Creation code here
}
@PostConstruct
void startUpTask() {
// Perform start up tasks
}
}
@Startup
@Singleton
public class Logger {
private Logger() {
// Creation code here
}
@PostConstruct
void startUpTask() {
// Perform start up tasks
}
}
@alextheedom#JavaEE
Java EE Implementation
•Specify dependent instantiation
@DependsOn("PrimaryBean")
@Startup
@Singleton
public class Logger {
...
}
@DependsOn("PrimaryBean")
@Startup
@Singleton
public class Logger {
...
}
@alextheedom#JavaEE
Java EE Implementation
@DependsOn("PrimaryBean")
@Startup
@Singleton
public class Logger {
private Logger() {
// Creation code here
}
@PostConstruct
void startUpTask() {
// Perform start up tasks
}
}
@DependsOn("PrimaryBean")
@Startup
@Singleton
public class Logger {
private Logger() {
// Creation code here
}
@PostConstruct
void startUpTask() {
// Perform start up tasks
}
}
@alextheedom#JavaEE
Java EE Implementation
•Conclusions so far
•Very different implementation
•Substantially less boilerplate code
•Enhancements via specialized annotations
@alextheedom#JavaEE
Java EE Implementation
•Further enhancements
•Fine grain concurrency management
•Container vs. bean managed
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class Logger {
...
}
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class Logger {
...
}
•What about method access?
@alextheedom#JavaEE
Java EE Implementation
•Method access
•LockType.WRITE and LockType.READ
@Lock(LockType.WRITE)
public void addMessage(String message) {
// Add message to log
}
@Lock(LockType.READ)
public String getMessage() {
// Get message
}
@Lock(LockType.WRITE)
public void addMessage(String message) {
// Add message to log
}
@Lock(LockType.READ)
public String getMessage() {
// Get message
}
@alextheedom#JavaEE
Java EE Implementation
•Method access timeout
•ConcurrentAccessTimeoutException
•Defined by annotation @AccessTimeout
•Class and method level
@AccessTimeout(value = 30, unit=TimeUnit.SECONDS)
@Lock(LockType.WRITE)
public void addMessage(String message) {
// Add message to log
}
@AccessTimeout(value = 30, unit=TimeUnit.SECONDS)
@Lock(LockType.WRITE)
public void addMessage(String message) {
// Add message to log
}
@alextheedom#JavaEE
Conclusion
•Substantially different manner of implementation
•Marked reduction in code (~50%)
•Implementation improved via specialized annotations
•Startup behavioural characteristics
•Fine grain control over concurrency and access timeout
@alextheedom#JavaEE
Factory Pattern
•Creational pattern
•Interface for creating family of objects
•Clients are decoupled from the creation
@alextheedom#JavaEE
Conventional Implementation
public class DrinksMachineFactory implements AbstractDrinksMachineFactory{
public DrinksMachine createCoffeeMachine() {
return new CoffeeMachine();
}
}
public class DrinksMachineFactory implements AbstractDrinksMachineFactory{
public DrinksMachine createCoffeeMachine() {
return new CoffeeMachine();
}
}
•Use it like so:
AbstractDrinksMachineFactory factory = new DrinksMachineFactory();
DrinksMachine coffeeMachine = factory.createCoffeeMachine();
AbstractDrinksMachineFactory factory = new DrinksMachineFactory();
DrinksMachine coffeeMachine = factory.createCoffeeMachine();
•Abstract factory
@alextheedom#JavaEE
Java EE Implementation
•CDI framework is a factory
public class CoffeeMachine implements DrinksMachine {
// Implementation code
}
public class CoffeeMachine implements DrinksMachine {
// Implementation code
}
•Use it like so:
@Inject
DrinksMachine drinksMachine;
@Inject
DrinksMachine drinksMachine;
@alextheedom#JavaEE
Java EE Implementation
•Problem! Multiple concrete implementations
public class CoffeeMachine implements DrinksMachine {
// Implementation code
}
public class SoftDrinksMachine implements DrinksMachine {
// Implementation code
}
public class CoffeeMachine implements DrinksMachine {
// Implementation code
}
public class SoftDrinksMachine implements DrinksMachine {
// Implementation code
}
@Inject
DrinksMachine drinksMachine;
@Inject
DrinksMachine drinksMachine;
•Which DrinksMachine to inject?
@alextheedom#JavaEE
Java EE Implementation
•Solution! Qualifiers
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface SoftDrink
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface SoftDrink
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface Coffee
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface Coffee
@alextheedom#JavaEE
Java EE Implementation
•Annotate respective classes
@Coffee
public class CoffeeMachine implements DrinksMachine {
// Implementation code
}
@Coffee
public class CoffeeMachine implements DrinksMachine {
// Implementation code
}
@SoftDrink
public class SoftDrinksMachine implements DrinksMachine {
// Implementation code
}
@SoftDrink
public class SoftDrinksMachine implements DrinksMachine {
// Implementation code
}
@alextheedom#JavaEE
Java EE Implementation
•Annotate injection points
@Inject @SoftDrink
DrinksMachine softDrinksMachine;
@Inject @SoftDrink
DrinksMachine softDrinksMachine;
@Inject @Coffee
DrinksMachine coffeeDrinksMachine;
@Inject @Coffee
DrinksMachine coffeeDrinksMachine;
@alextheedom#JavaEE
Java EE Implementation
•Conclusions so far
•No boilerplate code
•Container does all the hard work
•Disambiguation via qualifiers
•Remember
•Only JSR299 beans are ‘injectable’
@alextheedom#JavaEE
Java EE Implementation
•Dive deeper
•Producer methods
•Use it like so:
@Produces
@Library
public List<Book> getLibrary(){
// Generate a List of books called 'library'
return library;
}
@Produces
@Library
public List<Book> getLibrary(){
// Generate a List of books called 'library'
return library;
}
@Inject @Library
List<Books> library;
@Inject @Library
List<Books> library;
@alextheedom#JavaEE
Java EE Implementation
•Scope
•Determines when method called
•Life of object: @RequestScoped -> @ApplicationScoped
@SessionScoped
@Produces
@Library
public List<Book> getLibrary(){
// Generate a List of books called 'library'
return library;
}
@SessionScoped
@Produces
@Library
public List<Book> getLibrary(){
// Generate a List of books called 'library'
return library;
}
@alextheedom#JavaEE
Java EE Implementation
•Parameterized creation
public class LoggerFactory{
@Produces
public Logger logger(InjectionPoint injectionPoint) {
return Logger.getLogger(
injectionPoint.getMember()
.getDeclaringClass().getName());
}
}
public class LoggerFactory{
@Produces
public Logger logger(InjectionPoint injectionPoint) {
return Logger.getLogger(
injectionPoint.getMember()
.getDeclaringClass().getName());
}
}
@Inject
private transient Logger logger;
@Inject
private transient Logger logger;
@alextheedom#JavaEE
Java EE Implementation
•Conclusions so far
•Virtually any object can be made injectable
•Automatic per class configuration
@alextheedom#JavaEE
Harnessing the power of CDI
•A variation on the factory pattern
•Imaginative use of CDI
•Multiple implementations of the same interface
•Collect and select pattern
•Uses @Any, enums, annotation literals and Instance class
@alextheedom#JavaEE
Harnessing the power of CDI
•@Any
@Any
@Inject
private Instance<MessageType> messages
@Any
@Inject
private Instance<MessageType> messages
@alextheedom#JavaEE
Harnessing the power of CDI
•Distinguish between message types using qualifiers
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Message {
Type value();
enum Type{ SHORT, LONG }
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Message {
Type value();
enum Type{ SHORT, LONG }
}
@alextheedom#JavaEE
Harnessing the power of CDI
•Annotate our classes
@Message(Message.Type.SHORT)
public class ShortMessage implements MessageType{
// Short message implementation code
}
@Message(Message.Type.SHORT)
public class ShortMessage implements MessageType{
// Short message implementation code
}
@Message(Message.Type.LONG)
public class LongMessage implements MessageType{
// Long message implementation code
}
@Message(Message.Type.LONG)
public class LongMessage implements MessageType{
// Long message implementation code
}
@alextheedom#JavaEE
Harnessing the power of CDI
•Create an annotation literal for messages
public class MessageLiteral extends
AnnotationLiteral<Message> implements Message {
private Type type;
public MessageLiteral(Type type) {
this.type = type;
}
public Type value() {
return type;
}
}
public class MessageLiteral extends
AnnotationLiteral<Message> implements Message {
private Type type;
public MessageLiteral(Type type) {
this.type = type;
}
public Type value() {
return type;
}
}
@alextheedom#JavaEE
Harnessing the power of CDI
•Putting the puzzle together
@Inject
@Any
private Instance<MessageType> messages;
public MessageType getMessage(Message.Type type) {
MessageLiteral literal = new MessageLiteral(type);
Instance<MessageType> typeMessages =
messages.select(literal);
return typeMessages.get();
}
@Inject
@Any
private Instance<MessageType> messages;
public MessageType getMessage(Message.Type type) {
MessageLiteral literal = new MessageLiteral(type);
Instance<MessageType> typeMessages =
messages.select(literal);
return typeMessages.get();
}
@alextheedom#JavaEE
Harnessing the power of CDI
•Use it like so:
@Inject
private MessageFactory mf;
public void doMessage(){
MessageType m = mf.getMessage(Message.Type.SHORT);
}
@Inject
private MessageFactory mf;
public void doMessage(){
MessageType m = mf.getMessage(Message.Type.SHORT);
}
@alextheedom#JavaEE
Conclusion
•CDI removes need for factory pattern
•Container does all the hard work
•Substantially less boilerplate code
•Disambiguation via qualifiers
•Increased creativity
•Collect and select
@alextheedom#JavaEE
Other Patterns
•Facade
•Decorator
•Observer
@alextheedom#JavaEE
Façade Pattern
•Encapsulates complicated logic
•@Stateless, @Stateful
@Stateless
public class BankServiceFacade{
@Inject
private AccountService accountService;
}
@Stateless
public class BankServiceFacade{
@Inject
private AccountService accountService;
}
@Stateless
public class AccountService{}
@Stateless
public class AccountService{}
@alextheedom#JavaEE
Decorator Pattern
•Dynamically adds logic to an object
@alextheedom#JavaEE
Decorator Pattern
@Decorator
@Priority(Interceptor.Priority.APPLICATION)
public class PriceDiscountDecorator implements Product {
@Any
@Inject
@Delegate
private Product product;
public String generateLabel() {
product.setPrice(product.getPrice() * 0.5);
return product.generateLabel();
}
}
@Decorator
@Priority(Interceptor.Priority.APPLICATION)
public class PriceDiscountDecorator implements Product {
@Any
@Inject
@Delegate
private Product product;
public String generateLabel() {
product.setPrice(product.getPrice() * 0.5);
return product.generateLabel();
}
}
@alextheedom#JavaEE
Observer Pattern
•Notifies dependents of state change
public void trace(@Observes String message){
// Response to String event
}
public void trace(@Observes String message){
// Response to String event
}
@alextheedom#JavaEE
Final Conclusion
•Efficiency savings
•Greater control over behaviour
•New features enhance implementation
•Opens doors to new pattern design
#JavaEE @alextheedom
40% discount with promo code
VBK43
when ordering through
wiley.com
valid until 1st September
@YourTwitterHandle#DVXFR14{session hashtag} @alextheedom#JavaEE
Q & A
#JavaEE @alextheedom
Professional Java EE Design
PatternsAlex Theedom
@alextheedom
alextheedom.com
Thank You

Java days Lviv 2015

  • 1.
    #JavaEE @alextheedom Professional JavaEE Design PatternsAlex Theedom @alextheedom alextheedom.com
  • 2.
    @alextheedom#JavaEE Speaker’s Bio •Senior JavaDeveloper •Author: Professional Java EE Design Patterns •E-learning Platforms •Cash Machine Software •Microservice Based Lottery Systems •Spring and Java EE
  • 3.
    @alextheedom#JavaEE What to expect •What’sthe story •Why am I here? What’s the message? •Whistle stop tour •Design Patterns: what, when and why •Context Dependency Injection
  • 4.
    @alextheedom#JavaEE What to expect •DeepDive •Singleton Pattern •Factory Pattern •Harnessing the power (something special) •Quickie Patterns •Façade, Decorator, Observer •Q&A
  • 5.
    @alextheedom#JavaEE What’s the story •JavaEE changed design pattern implementation •Implementation has simplified •Implementation has been enhanced •Greater creativity •How? •I will show you today •Change is part of Java EE continued development
  • 6.
    @alextheedom#JavaEE Design patterns: 3W’S •Whatare design patterns? •Why do we need them? •When to use them?
  • 7.
    @alextheedom#JavaEE Context Dependency Injection •Simplifiesprogramming model •Annotations have replaced XML config files •Convention over Configuration •Resources are injected by type •@Inject and disambiguation @Qualifier •POJO (JSR 299 managed bean) •Otherwise @Producer
  • 8.
    @alextheedom#JavaEE Singleton Pattern •Ubiquitous andcontroversial but inescapable •Instantiated once •Not normally destroy during application life cycle
  • 9.
    @alextheedom#JavaEE Conventional Implementation public classLogger { private static Logger instance; private Logger() { // Creation code here } public static synchronized Logger getInstance() { if(instance == null) { instance = new Logger(); } return instance; } } public class Logger { private static Logger instance; private Logger() { // Creation code here } public static synchronized Logger getInstance() { if(instance == null) { instance = new Logger(); } return instance; } }
  • 10.
    @alextheedom#JavaEE Conventional Implementation •Only oneinstance of Logger created •Created by first call the getInstance() •Thread safe creation •Use it like so: Logger logger = Logger.getInstance();Logger logger = Logger.getInstance();
  • 11.
    @alextheedom#JavaEE Java EE Implementation @Singleton publicclass Logger { private Logger() { // Creation code here } } @Singleton public class Logger { private Logger() { // Creation code here } }
  • 12.
    @alextheedom#JavaEE Java EE Implementation •Onlyone instance of Logger created •Created by container (lazily) •Knows it’s a singleton because @Singleton •Use it like so: @Inject Logger logger; @Inject Logger logger;
  • 13.
    @alextheedom#JavaEE Java EE Implementation •Eagerinstantiation @Startup •Perform startup tasks @PostConstruct
  • 14.
    @alextheedom#JavaEE Java EE Implementation @Startup @Singleton publicclass Logger { private Logger() { // Creation code here } @PostConstruct void startUpTask() { // Perform start up tasks } } @Startup @Singleton public class Logger { private Logger() { // Creation code here } @PostConstruct void startUpTask() { // Perform start up tasks } }
  • 15.
    @alextheedom#JavaEE Java EE Implementation •Specifydependent instantiation @DependsOn("PrimaryBean") @Startup @Singleton public class Logger { ... } @DependsOn("PrimaryBean") @Startup @Singleton public class Logger { ... }
  • 16.
    @alextheedom#JavaEE Java EE Implementation @DependsOn("PrimaryBean") @Startup @Singleton publicclass Logger { private Logger() { // Creation code here } @PostConstruct void startUpTask() { // Perform start up tasks } } @DependsOn("PrimaryBean") @Startup @Singleton public class Logger { private Logger() { // Creation code here } @PostConstruct void startUpTask() { // Perform start up tasks } }
  • 17.
    @alextheedom#JavaEE Java EE Implementation •Conclusionsso far •Very different implementation •Substantially less boilerplate code •Enhancements via specialized annotations
  • 18.
    @alextheedom#JavaEE Java EE Implementation •Furtherenhancements •Fine grain concurrency management •Container vs. bean managed @Singleton @ConcurrencyManagement(ConcurrencyManagementType.BEAN) public class Logger { ... } @Singleton @ConcurrencyManagement(ConcurrencyManagementType.BEAN) public class Logger { ... } •What about method access?
  • 19.
    @alextheedom#JavaEE Java EE Implementation •Methodaccess •LockType.WRITE and LockType.READ @Lock(LockType.WRITE) public void addMessage(String message) { // Add message to log } @Lock(LockType.READ) public String getMessage() { // Get message } @Lock(LockType.WRITE) public void addMessage(String message) { // Add message to log } @Lock(LockType.READ) public String getMessage() { // Get message }
  • 20.
    @alextheedom#JavaEE Java EE Implementation •Methodaccess timeout •ConcurrentAccessTimeoutException •Defined by annotation @AccessTimeout •Class and method level @AccessTimeout(value = 30, unit=TimeUnit.SECONDS) @Lock(LockType.WRITE) public void addMessage(String message) { // Add message to log } @AccessTimeout(value = 30, unit=TimeUnit.SECONDS) @Lock(LockType.WRITE) public void addMessage(String message) { // Add message to log }
  • 21.
    @alextheedom#JavaEE Conclusion •Substantially different mannerof implementation •Marked reduction in code (~50%) •Implementation improved via specialized annotations •Startup behavioural characteristics •Fine grain control over concurrency and access timeout
  • 22.
    @alextheedom#JavaEE Factory Pattern •Creational pattern •Interfacefor creating family of objects •Clients are decoupled from the creation
  • 23.
    @alextheedom#JavaEE Conventional Implementation public classDrinksMachineFactory implements AbstractDrinksMachineFactory{ public DrinksMachine createCoffeeMachine() { return new CoffeeMachine(); } } public class DrinksMachineFactory implements AbstractDrinksMachineFactory{ public DrinksMachine createCoffeeMachine() { return new CoffeeMachine(); } } •Use it like so: AbstractDrinksMachineFactory factory = new DrinksMachineFactory(); DrinksMachine coffeeMachine = factory.createCoffeeMachine(); AbstractDrinksMachineFactory factory = new DrinksMachineFactory(); DrinksMachine coffeeMachine = factory.createCoffeeMachine(); •Abstract factory
  • 24.
    @alextheedom#JavaEE Java EE Implementation •CDIframework is a factory public class CoffeeMachine implements DrinksMachine { // Implementation code } public class CoffeeMachine implements DrinksMachine { // Implementation code } •Use it like so: @Inject DrinksMachine drinksMachine; @Inject DrinksMachine drinksMachine;
  • 25.
    @alextheedom#JavaEE Java EE Implementation •Problem!Multiple concrete implementations public class CoffeeMachine implements DrinksMachine { // Implementation code } public class SoftDrinksMachine implements DrinksMachine { // Implementation code } public class CoffeeMachine implements DrinksMachine { // Implementation code } public class SoftDrinksMachine implements DrinksMachine { // Implementation code } @Inject DrinksMachine drinksMachine; @Inject DrinksMachine drinksMachine; •Which DrinksMachine to inject?
  • 26.
    @alextheedom#JavaEE Java EE Implementation •Solution!Qualifiers @Qualifier @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.FIELD}) public @interface SoftDrink @Qualifier @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.FIELD}) public @interface SoftDrink @Qualifier @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.FIELD}) public @interface Coffee @Qualifier @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.FIELD}) public @interface Coffee
  • 27.
    @alextheedom#JavaEE Java EE Implementation •Annotaterespective classes @Coffee public class CoffeeMachine implements DrinksMachine { // Implementation code } @Coffee public class CoffeeMachine implements DrinksMachine { // Implementation code } @SoftDrink public class SoftDrinksMachine implements DrinksMachine { // Implementation code } @SoftDrink public class SoftDrinksMachine implements DrinksMachine { // Implementation code }
  • 28.
    @alextheedom#JavaEE Java EE Implementation •Annotateinjection points @Inject @SoftDrink DrinksMachine softDrinksMachine; @Inject @SoftDrink DrinksMachine softDrinksMachine; @Inject @Coffee DrinksMachine coffeeDrinksMachine; @Inject @Coffee DrinksMachine coffeeDrinksMachine;
  • 29.
    @alextheedom#JavaEE Java EE Implementation •Conclusionsso far •No boilerplate code •Container does all the hard work •Disambiguation via qualifiers •Remember •Only JSR299 beans are ‘injectable’
  • 30.
    @alextheedom#JavaEE Java EE Implementation •Divedeeper •Producer methods •Use it like so: @Produces @Library public List<Book> getLibrary(){ // Generate a List of books called 'library' return library; } @Produces @Library public List<Book> getLibrary(){ // Generate a List of books called 'library' return library; } @Inject @Library List<Books> library; @Inject @Library List<Books> library;
  • 31.
    @alextheedom#JavaEE Java EE Implementation •Scope •Determineswhen method called •Life of object: @RequestScoped -> @ApplicationScoped @SessionScoped @Produces @Library public List<Book> getLibrary(){ // Generate a List of books called 'library' return library; } @SessionScoped @Produces @Library public List<Book> getLibrary(){ // Generate a List of books called 'library' return library; }
  • 32.
    @alextheedom#JavaEE Java EE Implementation •Parameterizedcreation public class LoggerFactory{ @Produces public Logger logger(InjectionPoint injectionPoint) { return Logger.getLogger( injectionPoint.getMember() .getDeclaringClass().getName()); } } public class LoggerFactory{ @Produces public Logger logger(InjectionPoint injectionPoint) { return Logger.getLogger( injectionPoint.getMember() .getDeclaringClass().getName()); } } @Inject private transient Logger logger; @Inject private transient Logger logger;
  • 33.
    @alextheedom#JavaEE Java EE Implementation •Conclusionsso far •Virtually any object can be made injectable •Automatic per class configuration
  • 34.
    @alextheedom#JavaEE Harnessing the powerof CDI •A variation on the factory pattern •Imaginative use of CDI •Multiple implementations of the same interface •Collect and select pattern •Uses @Any, enums, annotation literals and Instance class
  • 35.
    @alextheedom#JavaEE Harnessing the powerof CDI •@Any @Any @Inject private Instance<MessageType> messages @Any @Inject private Instance<MessageType> messages
  • 36.
    @alextheedom#JavaEE Harnessing the powerof CDI •Distinguish between message types using qualifiers @Qualifier @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.TYPE}) public @interface Message { Type value(); enum Type{ SHORT, LONG } } @Qualifier @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.TYPE}) public @interface Message { Type value(); enum Type{ SHORT, LONG } }
  • 37.
    @alextheedom#JavaEE Harnessing the powerof CDI •Annotate our classes @Message(Message.Type.SHORT) public class ShortMessage implements MessageType{ // Short message implementation code } @Message(Message.Type.SHORT) public class ShortMessage implements MessageType{ // Short message implementation code } @Message(Message.Type.LONG) public class LongMessage implements MessageType{ // Long message implementation code } @Message(Message.Type.LONG) public class LongMessage implements MessageType{ // Long message implementation code }
  • 38.
    @alextheedom#JavaEE Harnessing the powerof CDI •Create an annotation literal for messages public class MessageLiteral extends AnnotationLiteral<Message> implements Message { private Type type; public MessageLiteral(Type type) { this.type = type; } public Type value() { return type; } } public class MessageLiteral extends AnnotationLiteral<Message> implements Message { private Type type; public MessageLiteral(Type type) { this.type = type; } public Type value() { return type; } }
  • 39.
    @alextheedom#JavaEE Harnessing the powerof CDI •Putting the puzzle together @Inject @Any private Instance<MessageType> messages; public MessageType getMessage(Message.Type type) { MessageLiteral literal = new MessageLiteral(type); Instance<MessageType> typeMessages = messages.select(literal); return typeMessages.get(); } @Inject @Any private Instance<MessageType> messages; public MessageType getMessage(Message.Type type) { MessageLiteral literal = new MessageLiteral(type); Instance<MessageType> typeMessages = messages.select(literal); return typeMessages.get(); }
  • 40.
    @alextheedom#JavaEE Harnessing the powerof CDI •Use it like so: @Inject private MessageFactory mf; public void doMessage(){ MessageType m = mf.getMessage(Message.Type.SHORT); } @Inject private MessageFactory mf; public void doMessage(){ MessageType m = mf.getMessage(Message.Type.SHORT); }
  • 41.
    @alextheedom#JavaEE Conclusion •CDI removes needfor factory pattern •Container does all the hard work •Substantially less boilerplate code •Disambiguation via qualifiers •Increased creativity •Collect and select
  • 42.
  • 43.
    @alextheedom#JavaEE Façade Pattern •Encapsulates complicatedlogic •@Stateless, @Stateful @Stateless public class BankServiceFacade{ @Inject private AccountService accountService; } @Stateless public class BankServiceFacade{ @Inject private AccountService accountService; } @Stateless public class AccountService{} @Stateless public class AccountService{}
  • 44.
  • 45.
    @alextheedom#JavaEE Decorator Pattern @Decorator @Priority(Interceptor.Priority.APPLICATION) public classPriceDiscountDecorator implements Product { @Any @Inject @Delegate private Product product; public String generateLabel() { product.setPrice(product.getPrice() * 0.5); return product.generateLabel(); } } @Decorator @Priority(Interceptor.Priority.APPLICATION) public class PriceDiscountDecorator implements Product { @Any @Inject @Delegate private Product product; public String generateLabel() { product.setPrice(product.getPrice() * 0.5); return product.generateLabel(); } }
  • 46.
    @alextheedom#JavaEE Observer Pattern •Notifies dependentsof state change public void trace(@Observes String message){ // Response to String event } public void trace(@Observes String message){ // Response to String event }
  • 47.
    @alextheedom#JavaEE Final Conclusion •Efficiency savings •Greatercontrol over behaviour •New features enhance implementation •Opens doors to new pattern design
  • 48.
    #JavaEE @alextheedom 40% discountwith promo code VBK43 when ordering through wiley.com valid until 1st September
  • 49.
  • 50.
    #JavaEE @alextheedom Professional JavaEE Design PatternsAlex Theedom @alextheedom alextheedom.com Thank You