D.S

www.adam-bien.com

Injecting Different Implementations Into An EJB 3 - Killing Factories : Adam Bien's Weblog

Injecting Different Implementations Into An EJB 3 - Killing Factories : Adam Bien's Weblog Adam Bien's Weblog « Java The Most Popula... | Main | EJB 3.1 BeanLocator... » Injecting Different Implementations Into An EJB 3 - Killing Factories In most cases the EJB 3 container relies on conventions and injects the one and only existing EJB 3 implementation. It is convenient because in vast majority of all cases you only have one single implementation of an interface. Because it is the only possible choice, additional configuration doesn't provide any added value. It wouldn't be DRY. But if you get an additional implementation of the interface - this approach will break. @Local public interface Service { public String getMessage(); } @Stateless public class DefaultService implements Service { public String getMessage() { return "Hello from: " + this.getClass().getName(); } } //additional implementation - breaks the DI conventions @Stateless public class SpecificService implements Service { public String getMessage() { return "Hello from: " + this.getClass().getName(); } } You will have to specify, what implementation has to be injected. You have two choices:  1. The use of annotations: @Stateless @WebService public class ClientAnnotationBean implements Client { @EJB(beanName="DefaultService") private Service service; public String getHello() { return this.service.getMessage(); } } The "DefaultService" in the @EJB annotation is the name of the EJB (DefaultService.class.getSimpleName()).  You will have to recompile the code the client on every change... 2. The use of XML-configuration. In this case you can skip the beanName attribute in the annotation and specify it in the  ejb-jar.xml. You could even entirely omit the @EJB annotation - but it doesn't provide additional benefits. You don't have to recompile your code, but provide and maintain an ejb-jar.xml file: @Stateless @WebService public class ClientXMLBean implements Client { @EJB private Service service; public String getHello() { return this.service.getMessage(); } } The particular implementation has to be specified in the ejb-jar.xml configuration then: <ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee"          version = "3.0"          xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"          xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">     <enterprise-beans>           <session>         <ejb-name>ClientXMLBean</ejb-name>         <ejb-local-ref>            <ejb-ref-name>com.abien.samples.di.client.ClientXMLBean/service</ejb-ref-name>            <local>com.abien.samples.di.service.Service</local>            <ejb-link>DefaultService</ejb-link>         </ejb-local-ref>     </session>   </enterprise-beans> </ejb-jar> In EJB 3.1 interfaces are actually superfluous for common cases . Interfaces are only needed for the encapsulation of multiple implementations. With DI and EJB 3 you don't need factories any more. The whole sample was pushed into: http://kenai.com/projects/javaee-patterns/ and tested with Glassfish v2 and Netbeans 6.5/6.7.1 [See also: " Real World Java EE Patterns - Rethinking Best Practices ", chapter 1, page 37 for more details about DI] Posted at 11:49AM Aug 03, 2009 by Adam Bien , Comments[9]  | Views/Hits: 6260 NEW workshop: HTML 5 and JavaScript Essentials , Three days in April 2017: from Java EE 7 Architectures over Microservices to Performance, Troubleshooting and Monitoring On demand workshops: Java EE 7: Bootstrap, Effective, Testing and Microservices available for streaming. Newsletter: airhacks.news A book about rethinking Java EE Patterns Comments: Killing factories...really? This is fine and good but factories are still an important part of your toolbox. The method described above only addresses the case when you know at compile time what bean you will need. A factory is still required when you can only determine a bean at runtime. Posted by todd on August 04, 2009 at 01:21 AM CEST # @Todd, exactly - this approach is static. With factories and reflection you could swap the implementation dynamically. BUT: in the context of a typical business app it is very rare. You will have to use a ServiceLocator then.... Factories inside the container are rarely needed, thanks for your comment!, adam Posted by Adam Bien on August 04, 2009 at 10:31 AM CEST # @Todd, see also: http://www.adam-bien.com/roller/abien/entry/ejb_3_1_beanlocator_when regards, adam Posted by Adam Bien on August 04, 2009 at 11:10 AM CEST # @EJB(beanName="DefaultService") private Service service; leads to the same tight coupling as private Service service = new DefaultService(); In fact this is a lookup even it is powered by DI mechanisms. Posted by Christian on December 09, 2009 at 06:01 PM CET # @Christian, "@EJB(beanName="DefaultService") private Service service; leads to the same tight coupling as..." with that name - yes. But you can name it however you want. You could even override the annotations