Sunday, December 20, 2015

Java EE revisits the Factory Pattern | alex.theedom



Java EE revisits the Factory Pattern | alex.theedom

CDI Framework

In Java EE we can take advantage of the CDI framework to create objects without knowing the details of their creation. The decoupling occurs as a result of the way Java EE implements inversion of control.
The most important benefit this conveys is the decoupling of higher-level-classes from lower level classes. This decoupling allows the implementation of the concrete class to change without affecting the client: reducing coupling and increasing flexibility.
The CDI framework itself is an implementation of the factory pattern. The container creates the qualifying object during application start up and injects it into any injection point that matches the injection criterion. The client does not need to know anything about the concrete implementation of the object, not even the name of the concrete class is known to the client.
@Inject
DrinksMachine drinksMachine;
Here, the container creates an instance of the CoffeeMachine concrete class, it is selected based on its interface DrinksMachine and injected wherever the container finds a qualifying injection point. This is the simplest way to use the CDI implementation of the factory pattern. However its not the most flexible.

Disambiguation

What happens if we have more than one concrete implementation of the DrinksMachineinterface?
1
2
3
4
5
6
7
public class CoffeeMachine implements DrinksMachine {
    // Implementation code
}
public class SoftDrinksMachine implements DrinksMachine {
    // Implementation code
}
Which implementation should be injected? SoftDrinksMachine or CoffeeMachine?
1
2
@Inject
DrinksMachine drinksMachine;
The container does not know and so deployment will fail with an “ambiguous dependencies” error.

Qualifiers

So how does the container distinguish between concrete implementations? Java EE gives us a new tool: Qualifiers. Qualifiers are custom annotations that mark the concrete class and the point where you want the container to inject the object.
Returning to our Drinks machine and the two concrete classes of the same typeCoffeeMachine and SoftDrinksMachine we would distinguish them by the use of two qualifier annotations:
1
2
3
4
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface SoftDrink
1
2
3
4
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface Coffee
We create one qualifier name SoftDrink. This will annotate the SoftDrinksMachine concrete class and Coffee will annotate the CoffeeMachine class.
The @Target annotation restricts where we can use these qualifiers to mark injection points, in this case on method and field injection points. The annotation with retention policy RUNTIME ensures that the annotation is available to the JVM through runtime.
The possible values for Target are: TYPE, METHOD, FIELD, PARAMETER.
The two concrete implementations of the DrinksMachine interface are annotated appropriately. The CoffeeMachine class is annotated @Coffee while the SoftDrinksMachineclass is annotated @SoftDrink.
1
2
3
4
@Coffee
public class CoffeeMachine implements DrinksMachine {
    // Implementation code
}
1
2
3
4
@SoftDrink
public class SoftDrinksMachine implements DrinksMachine {
    // Implementation code
}
Now you annotate the injection points. Use the qualifier @SoftDrink to denote where you want the container to inject the SoftDrinksMachine class and the qualifier @Coffee where you want the container to inject the CoffeeDrinkMachine. Now we have made it clear to the container where our concrete implementations should be injected and deployment will succeed.
1
2
@Inject @SoftDrink
DrinksMachine softDrinksMachine;
1
2
@Inject @Coffee
DrinksMachine coffeeDrinksMachine;
We have seen how Java EE’s CDI framework is an implementation of the factory pattern, how it hides the concrete implementation of an object and allows the creation to be decoupled from its use. We have seen how qualifiers are used to select the required implementation without the need to know anything about the objects creation.
It is important to remember that the CDI framework will only instantiate POJOs that meet all of the conditions of the managed beans specification JSR 299. But what if the object you want to inject doesn’t, does that mean we cannot take advantage of the CDI framework’s injection capabilities for classes that don’t comply. No it doesn’t. Java EE provides us with a solution. Lets dive deeper and look at how we can use the CDI framework to inject ANY class of ANY type into an injection point.
Producer Methods
Java EE has a feature called producer methods. These methods provide a way to instantiate and therefore make available for injection objects that don’t conform to the managed bean specifications such as objects which require a constructor parameter for proper instantiation. Objects whose value might change at runtime and objects whose creation requires some customised initialization can also be produced ready for injection via a producer method.
Lets have a look at a producer method which produces a List populated with Books objects.
1
2
3
4
5
6
@Produces
@Library
public List<Book> getLibrary(){
    // Generate a List of books called 'library'
    return library;
}
A list of Book objects will be injected into the injection point annotated @Library.
Use it like so:
1
2
@Inject @Library
List<Books> library;
An important feature of the producer method is its scope. This will determine when the method is invoked and for how long the object it produces will live.
By default the producer method scope is @DependentScoped. This means that it inherits the scope of its client.
We can extend this example further by giving it a wider scope. If we annotate the producer method @RequestScoped it will be invoked only once for each HTTP request in which it participate, lasting for the duration of the request.
1
2
3
4
5
6
7
@RequestScoped
@Produces
@Library
public List<Book> getLibrary(){
    // Generate a List of books called 'library'
    return library;
}
Possible scopes are:
RequestScoped – HTTP Request Scope
SessionScoped – HTTP Session Scope
ApplicationScoped – Shared across users
ConversationScoped – Interactions with JSF
DependentScoped – Default, inherits from client
  • The Good: easy to implement, no boilerplate code, works magically, any object can be made injectable, Automatic per class configuration
  • The Bad: named annotation is not type safe
  • and the ugly: object creation hidden, hard to follow execution flow, IDE should help
Read full article from Java EE revisits the Factory Pattern | alex.theedom

Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts