Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
Professional Java EE Design Patterns
Alex Theedom
@alextheedom
alextheedom.com
#JavaEE
@alextheedom
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
#JavaEE
@alextheedom
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
#JavaEE
@alextheedom
What to expect
• Deep Dive
• Singleton Pattern
• Factory Pattern
• Harnessing the power (something special)
• Quickie Patterns
• Façade, Decorator, Observer
• Q&A
#JavaEE
@alextheedom
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
#JavaEE
@alextheedom
Design patterns: 3W’S
• What are design patterns?
• Why do we need them?
• When to use them?
#JavaEE
@alextheedom
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
#JavaEE
@alextheedom
Singleton Pattern
• Ubiquitous and controversial but inescapable
• Instantiated once
• Not normally destroy during application life cycle
#JavaEE
@alextheedom
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;
}
}
#JavaEE
@alextheedom
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();
#JavaEE
@alextheedom
Java EE Implementation
@Singleton
public class Logger {
private Logger() {
// Creation code here
}
}
#JavaEE
@alextheedom
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;
#JavaEE
@alextheedom
Java EE Implementation
• Eager instantiation @Startup
• Perform startup tasks @PostConstruct
#JavaEE
@alextheedom
Java EE Implementation
@Startup
@Singleton
public class Logger {
private Logger() {
// Creation code here
}
@PostConstruct
void startUpTask() {
// Perform start up tasks
}
}
#JavaEE
@alextheedom
Java EE Implementation
• Specify dependent instantiation
@DependsOn("PrimaryBean")
@Startup
@Singleton
public class Logger {
...
}
#JavaEE
@alextheedom
Java EE Implementation
@DependsOn("PrimaryBean")
@Startup
@Singleton
public class Logger {
private Logger() {
// Creation code here
}
@PostConstruct
void startUpTask() {
// Perform start up tasks
}
}
#JavaEE
@alextheedom
Java EE Implementation
• Conclusions so far
• Very different implementation
• Substantially less boilerplate code
• Enhancements via specialized annotations
#JavaEE
@alextheedom
Java EE Implementation
• Further enhancements
• Fine grain concurrency management
• Container vs. bean managed
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class Logger {
...
}
• What about method access?
#JavaEE
@alextheedom
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
}
#JavaEE
@alextheedom
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
}
#JavaEE
@alextheedom
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
#JavaEE
@alextheedom
Factory Pattern
• Creational pattern
• Interface for creating family of objects
• Clients are decoupled from the creation
#JavaEE
@alextheedom
Conventional Implementation
• Abstract factory
public class DrinksMachineFactory implements AbstractDrinksMachineFactory{
public DrinksMachine createCoffeeMachine() {
return new CoffeeMachine();
}
}
• Use it like so:
AbstractDrinksMachineFactory factory = new DrinksMachineFactory();
DrinksMachine coffeeMachine = factory.createCoffeeMachine();
#JavaEE
@alextheedom
Java EE Implementation
• CDI framework is a factory
public class CoffeeMachine implements DrinksMachine {
// Implementation code
}
• Use it like so:
@Inject
DrinksMachine drinksMachine;
#JavaEE
@alextheedom
Java EE Implementation
• Problem!
Multiple concrete implementations
public class CoffeeMachine implements DrinksMachine {
// Implementation code
}
public class SoftDrinksMachine implements DrinksMachine {
// Implementation code
}
• Which DrinksMachine to inject?
@Inject
DrinksMachine drinksMachine;
#JavaEE
@alextheedom
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 Coffee
#JavaEE
@alextheedom
Java EE Implementation
• Annotate respective classes
@Coffee
public class CoffeeMachine implements DrinksMachine {
// Implementation code
}
@SoftDrink
public class SoftDrinksMachine implements DrinksMachine {
// Implementation code
}
#JavaEE
@alextheedom
Java EE Implementation
• Annotate injection points
@Inject @SoftDrink
DrinksMachine softDrinksMachine;
@Inject @Coffee
DrinksMachine coffeeDrinksMachine;
#JavaEE
@alextheedom
Java EE Implementation
• Conclusions so far
• No boilerplate code
• Container does all the hard work
• Disambiguation via qualifiers
• Remember
• Only JSR299 beans are ‘injectable’
#JavaEE
@alextheedom
Java EE Implementation
• Dive deeper
• Producer methods
@Produces
@Library
public List<Book> getLibrary(){
// Generate a List of books called 'library'
return library;
}
• Use it like so:
@Inject @Library
List<Books> library;
#JavaEE
@alextheedom
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;
}
#JavaEE
@alextheedom
Java EE Implementation
• Parameterized creation
public class LoggerFactory{
@Produces
public Logger logger(InjectionPoint injectionPoint) {
return Logger.getLogger(
injectionPoint.getMember()
.getDeclaringClass().getName());
}
}
• Use it like so:
@Inject
private transient Logger logger;
#JavaEE
@alextheedom
Java EE Implementation
• Conclusions so far
• Virtually any object can be made injectable
• Automatic per class configuration
#JavaEE
@alextheedom
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
#JavaEE
@alextheedom
Harnessing the power of CDI
• @Any
@Any
@Inject
private Instance<MessageType> messages
#JavaEE
@alextheedom
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 }
}
#JavaEE
@alextheedom
Harnessing the power of CDI
• Annotate our classes
@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
}
#JavaEE
@alextheedom
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;
}
}
#JavaEE
@alextheedom
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();
}
#JavaEE
@alextheedom
Harnessing the power of CDI
• Use it like so:
@Inject
private MessageFactory mf;
public void doMessage(){
MessageType m = mf.getMessage(Message.Type.SHORT);
}
#JavaEE
@alextheedom
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
#JavaEE
@alextheedom
Other Patterns
• Facade
• Decorator
• Observer
#JavaEE
@alextheedom
Façade Pattern
• Encapsulates complicated logic
• @Stateless, @Stateful
@Stateless
public class AccountService{}
@Stateless
public class BankServiceFacade{
@Inject
private AccountService accountService;
}
#JavaEE
@alextheedom
Decorator Pattern
• Dynamically adds logic to an object
#JavaEE
@alextheedom
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();
}
}
#JavaEE
@alextheedom
Observer Pattern
• Notifies dependents of state change
public void trace(@Observes String message){
// Response to String event
}
#JavaEE
@alextheedom
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
#JavaEE
@alextheedom
Q&A
#JavaEE
#DVXFR14{session hashtag}
@YourTwitterHandle
@alextheedom
Professional Java EE Design Patterns
Alex Theedom
@alextheedom
alextheedom.com
#JavaEE
Thank You
@alextheedom