StatelessSessionFactory + Beyond ServiceLocator

Discussions

J2EE patterns: StatelessSessionFactory + Beyond ServiceLocator

  1. Applicability
    This pattern is applicable when you have a lot of stateless session beans in your application and you want to have a uniform way of accessing them

    Participants
    * Service interface
     - This is a dummy interface which all Specific Services should extend.
    * SpecificService interface
     - This interface contains the declaration of all the business methods that usually go into a remote/local interface
    * SpecificSession interface
     - This interface just extends the SpecificService and ( EJBObject OR EJBLocalObject)
    * SpecificSessionHome interface
     - Just like any other home interface
    * SpecificSessionBean class
     - Just like any other session bean, implements SessionBean
    * ServiceLocator class
     - This has static methods getEJBLocalHome()/getEJBHome() [ This one is used to have the ability to cache contexts and home interfaces(). See ServiceLocator Pattern. ]
    * StatlessServiceFactory class
     - This contains a static method getService() which takes an argument that indicates what service the client is looking for. The argument could be a JNDI name or some other constant, that could ultimately be mapped to a JNDI Name/Class.
    * Client
     - Client that uses the factory class to locate the service


    Implementation
     Here's the partial reference implementation for the above participants.

    Service
    public interface Service {
    }

    SpecificService
    public interface HelloService extends Service {
      public void sayHello() throws ...;
      public void sayBye() throws ...;
    }

    SpecificSession
    public interface Hello extends HelloService,EJBLocalHome {
    }

    SpecificSessionBean
    public interface HelloBean implements SessionBean {
      .. implemenation of methods provided in Hello Service
    }

    ServiceLocator
    public class EJBHomeProvider {
     public static EJBLocalHome getEJBLocalHome(String jndiName) {
       /*
         Logic for creating a Home interface.
         Could have cached the context and home interface
       */
     }
    }

    StatelessServiceFactory
    public class StatelessServiceFactory {
     public static Service getService(String jndiName) {
      EJBLocalHome home = EJBHomeProvider.getEJBLocalHome(jndiName);
      Hello helloObj= home.create();
      return helloObj;
     }
    }

    Client
    public class SomeClient {
     ....
     HelloService helloService = (HelloService)StatelessServiceFactory.getService(ServiceConstants.HELLO);
      /* Here ServiceConstants could contain the list of all JNDI Names */
    }

     The above example can be extended to get any specific service. I think this pattern is more applicable with Local Stateless Session Beans and especially when there is excessive usage of many stateless session beans all over the application.

    Please let me know your comments on this.

    Thanks
     Kiran

    Threaded Messages (38)

  2. Why can't we use the above pattern for getting instances of Entity Beans too ?
  3. Usually entity beans have overloaded create methods. And each type of entity bean could take different number of arugments in their create methods.

     Hence it is not possible to completely avoid the invocation of create methods for entity beans.

     (OR) even if we find a way to modify the getService method to take dynamic number or arguments in the form of an array or some other datastructure , it creates more confusion and is error prone than the problem it tries to solve.
  4. Alternate JNDI?!?![ Go to top ]

    Are you suggesting a wrapper over JNDI?
    Apart from this, your pattern is nothing more than a
    mere *instance of* a factory pattern!

    Anyway, looking at the pattern:
    1. Why would I want to access 'n' EJBs the same way?
    2. Why should I extend from an interface just to enable
    uniform access?
    3. Assuming that this is fair, let us extend this concept.
    Why can't I have a factory for EJBObject itself?

    The only thing you are suggesting is that there is some
    component in the system which wraps JNDI. I wonder how good
    this is.
    -Siplin
  5. Alternate JNDI?!?![ Go to top ]

    Thanks for your valuable feedback.

    I made a minor mistake in the implementation section one of the particpants presented in the pattern

    SpecificSession
    This is how I presented it eariler
    public interface Hello extends HelloService,EJBLocalHome { }
    However the correct declaration is
    public interface Hello extends HelloService,EJBLocalObject {
    }

    I agree that this is not a whole new pattern , but what I tried to show was how a set of known patterns can be used to acheive something useful. Its a combination of Factory , Service Locator patterns. Yes this pattern also incorporates JNDI Wrapper in the form of a Service Locator but there is more than that.

    I was looking at the Business Interface pattern inside the 'EJB Patterns Book' on this site and it has many reasons why we need to have one additional interface. This will help us resolve quite a few issues at compile time than at build or deployment time. Please see Business Interface pattern for this.

    To follow the Business Interface Pattern I will have to make a minor change in the presented pattern.

    SpecificSessionBean
    This should implement both SessionBean and SpecificService interfaces.

    public interface HelloBean implements SessionBean,HelloService{
      .. implemenation of methods provided in Hello Service
    }

    Now that we are more convinced with the use of this pattern..
    I am not too sure if we can extend this to have a Factory of EJBObject itself. Because once we say EJBObject then stateful session beans and Entity Beans come into picture which can not be handled easily by the above pattern.

    Kiran
  6. Isn't this just Business INterface?[ Go to top ]

    Isn't this just the "Business INterface" pattern from the EJB Design patterns book available from this site?
  7. Isn't this just Business INterface?[ Go to top ]

    Thanks for mentioning about the Business Interface. I had a look at the Business Interface Pattern today.

     The pattern I presented earlier is not Business Interface. However I noticed that by modifying one of the participants it will have Business Interface incorporated.

    Detail of the particpant to be changed
    SpecificSessionBean
    This should implement both SessionBean and SpecificService interfaces.

    public interface HelloBean implements SessionBean,HelloService{
      .. implemenation of methods provided in Hello Service
    }

    Now with this in place this pattern is more than a Business Interface, it has ServiceFactory and ServiceLocator as well. All 3 patterns together are used to acheive something useful.


    One more advantage is we could add one more method 'recyleService(Service s)'to the StatelessServiceFactory class. getServcie() and recyleService() methods could be used to gain more control on the instances of stateless session beans [ though not required in many cases ]

    ..Kiran
  8. Isn't this just Business INterface?[ Go to top ]

    Buddy,
    this is nothing but part of business delegate pattern. This is normally used by most of the EJB applications to provide to its client a common gateway to interface with the server.

    Especially to interface with other applications. Question of using the same pattern for entity beans can not arise attall becose u never expose ur Entities to others.
  9. Isn't this just Business INterface?[ Go to top ]

    I agree that this is part of the Business Delegate Pattern.
    However, Business Delegate is more of a wrapper and does'nt worry about type casting. And usually we provide delegates for only those beans that have to be exposed to external clients so that they dont have to worry about type casting, exception handling etc.. The pattern I presented above will mostly be used on the server side for getting access to other beans. For example a Facade getting access to other components that make up the facade.

     It is interesting to note that the particualr scenario that I presented above uses a combination of so many patterns to various degrees.

     I found the above pattern useful in our application, However I will have to do more R&D on its usage in other applicaion scenarios.

    Kiran
  10. Your design pattern is a nice concept but as it is described in your post it cannot be implemented. In fact, the StatelessServiceFactory will generate an error at compile time:

        [javac] symbol : method create ()
        [javac] location: interface javax.ejb.EJBLocalHome

    javax.ejb.EJBLocalHome does not have a create() method.

    To circumvent this problem, you have to add a HelloServiceLocalHome interface to the design pattern which will replace the session bean's localHome interface:

    package foo;

    import javax.ejb.EJBLocalHome;
    import javax.ejb.CreateException;

    public interface HelloServiceLocalHome extends javax.ejb.EJBLocalHome
    {
       public HelloServiceLocal create() throws javax.ejb.CreateException;
    }

    The create() method in this interface returns (a child of) the uniform bean type (HelloService). You also need a HelloServiceLocal interface (better naming convention than Hello in my opinion):

    package foo;

    import javax.ejb.EJBLocalObject;

    public interface HelloServiceLocal extends HelloService,javax.ejb.EJBLocalObject
    {

    }

    The design of the StatelessServiceFactory is incorrect in this pattern. It should have a getHelloService(String jndiName) method - instead of getService - that would look like this:

    public HelloService getHelloService(String jndiName) throws javax.ejb.CreateException
    {
       return ((HelloService)((HelloServiceLocalHome)EJBHomeProvider.getEJBLocalHome(jndiName)).create());
    }

    (Caution: this baby can also throw the unchecked java.lang.ClassCastException).

    This implicates the Service interface is not required and the StatelessServiceFactory should implement a factory method per specific service. From a practical point of view this should not cause any troubles because in your original design the client has to cast to a specific service anyway.

    Last but certainly not least, every stateless session bean that implements the HelloService interface should have HelloServiceLocal and HelloServiceLocalHome defined as local and localHome interface respectively in ejb-jar.xml:

          <local-home>foo.HelloServiceLocalHome</local-home>
          <local>foo.HelloServiceLocal</local>

    That should do it. Unfortunately EJBGen does not support all this (fortunately we have sed).

    Anyway, your posting has put me on the right track for which I am grateful.

    kr

    Steven Devijver
  11. Hi Steven, Thanks for all the valuable suggestions.

    * You are very true that we need a HelloServiceLocalHome. I am sorry for not mentioning about it ( I thought it was very obvious to have a LocalHome for every LocalService returning an object of type LocalService in their create methods. It was my mistake not to mention that )

    * I liked the naming convention you suggested.

    * I agree that we should have the localhome and local interface entries inside the ejb-jar.xml with out which the container would'nt recognize that we are using local interfaces.

    * I still think
      public Service getService(String jndiName){}
      is more appropriate than
     public HelloService getHelloService(String jndiName) {}
      for a couple of reasons.

     1) Once you are done with a particular service you might want to recycle it. The current implementation of recycleService is ..
       public void recyleService(Service s) { //call remove on ejb }

     However if we have to go your route we will end up having a seperate method declaration for recyling all services and it would be a overhead. for ex:
      public void recyleHelloService(HelloService s) {}
      public void recyleByeService(ByeService s) { }

     Hence it makes sense to have the Service interface.

    2) There are no strong reasons for us to provide different methods for getting different services especially when those services are not part of the Session Facade and not used in the presentation tier. Instead we could do with
    public Service getService()

    * However when we expose services to the presentation tier it is not a good idea for them to get the generic Service and cast it to specific service. This is when your idea of providing a getSpecificService is more handy. But a business delegate would be more appropriate in those cases.
     In such a case I would like to suggest a small change to the method declaration. Instead of
      public HelloService getHelloService(String jndiName) { }
    it should be ..
      public HelloService getHelloService() { }
      Here , it is the responsibility of the getHelloService method to determine the jndiName corresponding to HelloService.

    * So I guess we do need a Service interface and getService() method. In addition you might want to provide a few methods like getXXService() in cases where they are exposed to clients of presentation tier.

    Here's a complete UML of the pattern
    UML Representation

    Thanks
     Kiran
  12. Hi Kiran,

    The generic Service and getService scheme simply won't work with EJB. As you stipulated we indeed need a home interface. Say we would create a ServiceLocalHome interface:

    package foo;

    import javax.ejb.EJBLocalHome;
    import javax.ejb.CreateException;

    public interface ServiceLocalHome extends javax.ejb.EJBLocalHome
    {
      public void ServiceLocal create() throws javax.ejb.CreateException;
    }

    This would then be the ServiceLocal interface:

    package foo;

    import javax.ejb.EJBLocalObject;

    public interface ServiceLocal extends Service, javax.ejb.EJBLocalObject
    {

    }

    The ServiceLocal interface only implements the Service interface and thus contains no business methods.

    Next you would need to deploy your session beans with ServiceLocalHome as localHome and ServiceLocal as local interfaces. Calling a bean in StatelessServiceFactory.getService() would be like this:

    public Service getService(String jndiName) throws javax.ejb.CreateException
    {
      return ((Service)((ServiceLocalHome)EJBHomeProvider.getEJBLocalHome(jndiName)).create())
    }

    From a pure design perspective I agree with what you are saying.

    Here's the catch: a deployment time, ejbc will create stub classes for each EJB based on their specific localHome and local classes. As the local interface does not specify any business methods because it does not extend a specific interface (HelloService) your bean has no methods to call.

    You could argument that each bean that implements a specific service (HelloService) needs to be deployed with a generic localHome (ServiceLocalHome) and a specific local (HelloServiceLocal) interface. The specific local interface would then extend the Service interface. However, the create() method of a localHome interface for an EJB needs to return the local interface of that EJB (this is mandatory).

    Furthermore, you cannot inherit an interface that already contains a create method (say: public ServiceLocal create() throws ... ;). This would generate an error at compile time.

    This is where your design hits the wall. The create() method of a specific localHome interface needs to return the specific local interface. So getService() is not a option because the common ServiceLocal does not implement any business methods.

    But do not worry, your design is very useful this way. The drawback from the design perspective is quickly forgotten when you implement this beauty.

    For example, because of your posting I have been able to design a message-driven bean that calls create on an ActionBeanLocalHome (I know, Struts ...) which returns an ActionBeanLocal object. The ActionBean interface has one method: executeAction() with as parameter the (XML) content of the message.

    The jndiName that has to be resolved is determined based on the value of a message property and is configured in a properties files. So, the MDB can call many different beans without knowing it and the functionality can be extended by simply deploying more beans and adding them to the properties file.

    It's real good stuff.

    (I don't use an StatelessServiceFactory so I'm not bothered by getSpecificService().)

    By the way, EJBGen does support this by means of @ejbgen:ejb-local-ref and @ejbgen:ejb-ref.

    kr

    Steven Devijver
  13. Hi Steven,

     I have read your reply. What I can conclude is you got some part of the pattern wrong than what I intended to present. May be I should improve my writing skills.

     I have applied this pattern in a production system with more than 100 EJBs. And everything works fine.

     Your following comments made me conclude that you got the pattern wrong.

    The generic Service and getService scheme simply won't work with EJB
    The ServiceLocal interface only implements the Service interface and thus contains no business methods
    return ((Service)((ServiceLocalHome)EJBHomeProvider.getEJBLocalHome(jndiName)).create())

     Instead of me trying to explain the whole pattern again here, I would like to take this discussion offline for a while ( email/phone) and write the conclusions here.

     Please let me know if we can have a quick discussion. If yes, please email me at digital_think@yahoo.co.in

     Once again thanks for the valuable feedback.

    -Kiran
  14. Hi Kiran,

    I have encountered the same problem or probably in a same position to develop a methodology to have uniform access to the beans with Business Delegates(BD) between client and ejb.

    1. I didn't prefer the idea of having one-to-one relationship with BD and Bean inorder to decouple client and ejb layer.Because most of my beans have a same method signatures and there is no point in having separate BD for each bean which only adds up the code.

    I had read all the postings and the way you had mentioned your pattern looks much similar to what I have been thinking to implement.Let me try and post if I was successful.

    In some consecutive postings you had mentioned that there should be some inclusion in ejb-jar.xml and include home interface. Can you please summarize and post what all to be included apart from the coding of interfaces and beans which you had mentioned in your first posting.

    Thanks
    Viji
  15. To help understand the pattern better, I am providing some sample code for all the components involved in developing a stateless session bean using this pattern. To make things simple, I have removed the exception handling code. Comments on each component are provided to give additional details/alternatives to the component.

    Service.java
    public interface Service
    {
    }
    Comments:
    This interface should be extended by all other LocalServices. It just indicates that the component will be used as a service

    LocalGreetingService.java
    public interface LocalGreetingService extends Service
    {
        public String sayHello();
        public String sayGoodBye();

    }
    Comments:
    This is where you provide the declerations of all your business methods. With out this pattern these declarations would usually go to Remote/Local interface of the bean. For the advantages of this approach look into Business Interface pattern.

    LocalGreeting.java
    public interface LocalGreeting extends EJBLocalObject, LocalGreetingService
    {
    }
    Comments:
    This is your actual Local interface extending the EJBLocalObject. This interface is empty, methods are inherited from the LocalxxxService.

    LocalGreetingHome.java
    public interface LocalGreetingHome extends EJBLocalHome
    {
        public LocalGreeting create() throws CreateException;

    }
    Comments:
    This is the Local Home interface. This is just like any other home interface. No special changes are made to this component as part of this pattern.

    GreetingBean.java
    public class GreetingBean implements javax.ejb.SessionBean,LocalGreetingService
    {
        // business logic methods
        public String sayHello() {
         return "Hello Friends";
        }
        
        public String sayGoodBye() {
         return "Catch you soon";
        }
        
    }
    Comments:
    Observe that the EJB implements LocalxxxService. Using this approach you could find problems at compile which otherwise would come at deploy time. See Business Interface pattern for more details.

    ServiceLocator.java
    private static EJBLocalHome getEJBLocalHome(String beanHomeName) {
        
    EJBLocalHome home = null;
    Context iCtx = getInitialContext();
    home = (EJBLocalHome) PortableRemoteObject.narrow( iCtx.lookup(beanHomeName), EJBLocalHome.class);

    return home;

    }
    Comments:
    This is the component which has an optimized way of looking for Home interfaces. In this code sample caching of context and home interfaces is hidden for simplicity. See Service Locator pattern for better implementations of this.

    StatelessServiceFactory.java
    public class StatelessServiceFactory {
          
        public static Service getService(String jndiName)
        {
         EJBLocalHome home = null;
         home = ServiceLocator.getEJBLocalHome(jndiName);
            Method create = home.getClass().getMethod("create", null);
            EJBLocalObject obj = (EJBLocalObject) create.invoke(home,null);
            return (Service) obj;

        }
        public static void recycleService(Service service)
        {
            if (service instanceof EJBLocalObject)
               ((EJBLocalObject)service).remove();
        }

    }
    Comments:
    This is the factory which provides the actual services, hiding the lookup of home interfaces and creation of services from the client. This internally uses Service Locator to get Cached Home Objects. One disadvantage with this is the clients will have to always cast it to the specific service. You can overcome this by providing specific methods like getXXXService(),getYYYService() which return specific services instead of a generic Service.

    JNDIConstants.java
    public class JNDIConstants {
    public static final String HELLO_SERVICE = "com.freejava.samples.LocalGreetingHome";
    public static final String OTHER_SERVICE = "com.freejava.samples.LocalSomeOtherHome";

    }
    Comments:
    This is a place holder to map all JNDI Names to Service constants. There could be various implementations of this JNDIConstants calss. Please refer to other Core J2EE Patterns for more details on this.

    ejb-jar.xml
    <ejb-jar>
      <enterprise-beans>
        <session>
          <description>Sample</description>
          <display-name>Greeting</display-name>
          <ejb-name>Greeting</ejb-name>
    <local-home> com.freejava.samples.LocalGreetingHome </local-home>
    <local> com.freejava.samples.LocalGreeting </local>
    <ejb-class> com.freejava.samples.GreetingBean </ejb-class>
          <session-type>Stateless</session-type>
          <transaction-type>Container</transaction-type>
        </session>
      </enterprise-beans>
      <assembly-descriptor>
        <container-transaction>
          <method>
            <ejb-name>Greeting</ejb-name>
            <method-name>*</method-name>
          </method>
          <trans-attribute>Supports</trans-attribute>
        </container-transaction>
      </assembly-descriptor>
    </ejb-jar>
    Comments:
    Observe the use of <local-home> and <local> tags.

    ClientServlet.java
    public class ClientServlet extends HttpServlet {
        public void doGet(HttpServletRequest req, HttpServletResponse resp) {
    LocalGreetingService greetingService = (LocalGreetingService) StatelessServiceFactory.getService(JNDIConstants.HELLO_SERVICE);
    System.out.println(greetingService.sayHello());
            StatelessServiceFactory.recycleService(greetingService);
        }
        
    }
    Comments:
    Client to the Service could be any component like SesssionEJBs, Servlets, JSPs etc. Clients get the service using the factory, use it and recycle it. Observe that the client code does'nt even bother about home interfaces, remote interfaces and other complex exceptions that we usually have to deal with. As I mentioned above , one disadvantage is that the Clients have to cast it to the specific service (ex: LocalGreetingService) and should also know the JNDIconstant referring to the service. If you think this is a problem, you could provide a public LocalGreetingService getGreetingService() method inside StatelessServiceFactory which avoids casting. In this case the client does'nt even have to pass the JNDIConstant since we will place that logic in getGreetingService().

    I welcome your suggestions.
     Kiran
  16. Forgot to add, one last thing.

    Specify the local-jndi-name. For weblogic users, this entry needs to be added inside weblogic-ejb-jar.xml

    <local-jndi-name>com.freejava.samples.LocalGreetingHome </local-jndi-name>
  17. Steven and I had a couple of offline discussions regarding the confusion in understanding the pattern.

     Here's what went in our emails..


    From: ...| This is Spam | Add to Address Book
    To: digital_think at yahoo dot co dot in
    Subject: RE: StatelessSessionFactory + Beyond ServiceLocator
    Date: Fri, 25 Apr 2003 08:34:50 +0100
           

    Hi Kiran,

    Sorry for the late response, but the last week has been a holiday here
    in
    the UK (its Easter!).

    First, thanks for the code. Having looked at it, it has answered my
    questions! I had wondered how you could create a Service instance,
    given
    that all of the specific home interfaces have no common ancestry. Now
    that I
    see your factory uses the EJB<Local>Home interface and reflection to
    access
    the "create" method, it all makes sense!

    Thanks once again, your design has made my code much better!

    Cheers,
    Paul

    -----Original Message-----
    From: kiran kumar [mailto:digital_think at yahoo dot co dot in]
    Sent: 09 April 2003 23:46
    To: Paul
    Subject: Re: StatelessSessionFactory + Beyond ServiceLocator


    Hi Paul,

     Good to hear from you.

    Here is the link for the UML diagram of the pattern.
    http://in.groups.yahoo.com/group/freejava/files/beyondservice.gif

     As we were discussing ..
      1) we have a dummy Service interface and all
    specific services extend the Service interface.
      2) Each specific service will have the business
    methods
      3) Actual local/remote interface will extend the
    specific service [ and thus will contain business
    methods ]
      4) EJB will implement the specific service and
    sessionbean [ not the local/remote interface ]. This
    step is nothing but business interface pattern.

    Please find the code attached with this mail and
    ignore the package names.

    Your feedback is most welcome.

    Thanks
     Kiran

     --- ... wrote: > Hi Kiran,
    >
    > I've just read your pattern on the server-side, and
    > looked at the last
    > comment regarding "no business methods on the
    > Service interface". As there
    > is no follow up, can you explain why this comment is
    > wrong or maybe supply
    > some code?
    >
    > Cheers,
    > Paul
    >
  18. Hi all,

    I tried to implement the pattern that was discussed here, in my application.

    I find a bottle neck when I try to apply this. Let me explain what I'm trying to do and kindly pinpoint where I miss to cope with the logic or design.

    I have many stateless session beans.They are accessed by Action class(Structs) via a ServiceLocator(ServiceLocator pattern). Here, I would like to include Business Delegate since my beans has to be accessed by any or many clients. So, I introduced the Business Delegate(BD) pattern. Again, I do not want to have BD for each bean, because almost all my beans have similar or same method signatures. So, I tried to first group the functionalities, say for 2-3 beans having same type of calling and accessing logic(or method signature), one BD would do. At that point I was thinking of generalised way of accessing my beans. So, I tried to use the above discussed pattern logic of Mr.Kiran. I'm through till I get my home interface using the jndiName parameter, but I'm forced to typecast to the specific service inorder to call my business method(which is quiet right) in my business delegate which I would like to avoid. I want to access them dynamically , then my accessing logic will be more generic whatsoever the number of beans that come in future. I just need to add the jndiConstants in the ServiceFactory and no other classes are touched.

    Hope I'm understandable..

    Thanks in advance for any motivations offered..
    Viji
  19. Thanks for taking time to analyze and use the pattern.

     If I got your requirement right, you want to avoid type casting to specific service (for both existing and new services ).

     As I mentioned in one of my earlier posts, if you want to avoid type casting then you should provide getXXXService method inside StatelessServiceFactory. This way you can centralize the typecasting logic inside getXXXSerive method which returns a specific service.

    Lets take an example here. If you are trying to access a service named MyService.
    With typecasting:
     MyService myService = (MyService)StatelessServiceFactory.getService(JNDIConstants.MYSERVICE);
    Without typecasting:
     MyService myService = StatelessServiceFactory.getMyService();

    If you are looking for something more generic than the above two approaches, at this moment I can't think of any. However in most cases, I feel the above approaches are generic enough.

    I welcome if someone has any thoughts on making this more generic.
  20. theclientside[ Go to top ]

    Yo! Thats pretty generic already. By the mention of Struts I guess you are talking about the client itself having to do the casting or calling getXXXservice(). We had a specific scenario with sessions that were fine grained pass-thrus to entities. From (many) clients we called standardized CRUD operations in a single client-side class maintained by the service team e.g.: ServiceManager.createObj(Constants.XXX_SERVICE, attributesArray), and it dealt with the locator, cast and handled exceptions. It kept the exception handling centralized and made the interface exposed to the client resistant to change. One downside is that you lose compile-time checking and had to confirm what to put in the array by reading the latest UML or exporting the object model. You could pass DTOs instead, I suppose. Work in Command pattern if you want more indirection? IT's been fun, thanks.
  21. Other than being a good practice to accomdomate any future extensions, is there any other good reason for the marker interface.

    A few months for one of our implementations i wrote a generic method which returns the EJB stub for any stateless session EJB as follows.

    homeCache is a hashmap instance that caches home stubs

     public Object getEJBInstance(String homeJNDIName) throws JNDIServiceException
            {
               Object homeInstance = homeCache.get(homeJNDIName);


               if (homeInstance == null)
               {
                   homeInstance = JNDIService.findHome(homeJNDIName);
               }

               // invoke the create method on the home instance. Since all
               // our beans are stateless session beans, the only create
               // method is the one with no parameters
               Class homeClass = homeInstance.getClass();
               Class [] emptyParamTypes = new Class[0];
               Object ejbInstance = null;
               try
               {
                    Method createMethod = homeClass.getMethod(STATELESS_CREATE_METHOD_NAME,emptyParamTypes);
                    Object [] emptyParamObjs = new Object[0];
                    ejbInstance = createMethod.invoke(homeInstance,emptyParamObjs);
                    logger.debug("*****EJB Instance*****"+ejbInstance);
                }
                catch (java.lang.NoSuchMethodException e)
               {
                   logger.debug(e.getMessage());
                   return null;
               }
               catch (java.lang.IllegalAccessException e)
               {
                    logger.debug(e.getMessage());
                    return null;
               }
               catch (java.lang.reflect.InvocationTargetException e)
               {
                   logger.debug(e.getMessage());
                   return null;
               }

                return ejbInstance;
            }
  22. The core implementation of getting the service is pretty much similar to the code that you have provided. You can find sample code in one of my earlier patterns.

      I am sure Service will be more specific than just returning a generic Object.

     When you want to recyle your services , it might be more appropriate for the method signature to be recycleService(Service s)
    than recyleService(Object o)

      In a bigger scenario, you could have different Service Engines part of an AbstractService Factory, which provide services in different ways [ for ex: some cached , some uncached , some remote, some local etc... ]. In all these components it is easy to deal with the concept of Service and than a generic Object. It will also make sure at compile time, the clients of these objects are passing valide services than generic Objects.

     If you dont want to get into this whole Service stuff, then I would recommend that you return an EJBObject instead of Object.

    Hope that helps.
  23. What I have implemented...[ Go to top ]

    From all your thoughts put together, I have implemented the following way.

    The call from the client is same as what we have discussed so far..(getService(jndiConstants)).
    In my BusinessDelegate(BD), in the init() method, I cast only to EJBObject when there is home.create().But when many beans have a same method signature(like getSomething(...), then I typecast them there in the method according to the jndiConstants. And then call the method using the corresponding Remote interface like below.

    public class BusinessDelegate1{

    public String getSomething(String x, int y, String z){
      switch(jndiConstant){

        case ServiceFactory.service1:
          Service1 service = (Service1)ejbObject;
          service.getSomething(....);
          break;
     
       case ServiceFactory.service2:
    ..................
    ..................

      }
    }
    }

    Even though I couldn't make it more generic, it is somewhat changeable and I create the remote objects only when necessary and only one at a time.

    Kiran, I got ur message of recycleService(serviceName).. all caching etc.., But I'm yet to reach there...

    Please tell me, if I'm wrong or miscalculate my coding logic.

    Thanks all for your inputs.
  24. What I have implemented...[ Go to top ]

    Hi Viji,
     
     From what I can make , you are trying to refer to multiple services from with in a single Business Delegate. Usually Business Delegate is used to represent a particular service with out the client having to deal with the lookup & creation of that service.

     Trying to refer to multiple Services having the same method name from within a single Business Delegate is not very convincing.

     I am afraid that you might have to change the way you have implemented the BusinessDelegate.
     
     Please refer to the BusinessDelegate pattern.

     If possible, try 2 give more detail about the problem that you are trying to solve.

    Thanks
  25. Just curious[ Go to top ]

    Just curious, why and when would you want to recycle a stateless session bean and what are the implications of this action?
  26. Just curious[ Go to top ]

    Finally, it is clear that some of the patterns listed here and specifically this one is nothing but a glorified utility method, embellished by extraneous interfaces to look like a pattern.
  27. Just curious[ Go to top ]

    \Mahesh\
    Finally, it is clear that some of the patterns listed here and specifically this one is nothing but a glorified utility method, embellished by extraneous interfaces to look like a pattern.
    \Mahesh\

    Yes, that sums it up pretty well.

       -Mike
  28. Just curious[ Go to top ]

    Hi Mike & Mahesh,

     I completely agree with you guys. This is not a pattern from out of the blue. It just show cases how some well known patterns can together be used to achieve some useful results. I had mentioned the same in some of my earlier postings :)

     I appreciate your comments. It would be great if you guys can take this (Utility) to the next level and make it more useful to more developers.

    Kiran
  29. Just curious[ Go to top ]

    I dont have a convincing answer for this for a long time. After doing some R&D, forums and EJBSpec, I realized that it is always better to recycle by calling the remove method irrespective of the bean type.

     One convincing explanation is, if for some reason you convert the Stateless Session Bean to a Stateful Session Bean, then you will have to modify all your clients (if they did'nt recycle earlier).

     It is also better to explicitly recycle, since what happens when you dont recycle varies from container to container.

     After the above comments, I should admit that I still dont have convincing answers as to why we should recycle, but I believe that it is better to recyle than not to.
  30. Just curious[ Go to top ]

    Kiran,

    This pattern, if we can call that was specifically intended for the usage for the creation of stateless session ejbs and not stateful session ejbs. It will not work in it's current form as a factory for stateful session ejbs. Hence your defense that if you plan to convert your beans from stateful to stateless doesn't make sense.

    I am not trying to say that this utility method that you have proposed is not useful. I am concerned that the unnecessary embellishments to make it look good are just that, 'unnecessary' and in some cases harmful, as in the case of the invocation of the ejbRemove method. What you are caching in your factory instance is a stub (in case of weblogic it itself has the knowledge to load balance). When ejbRemove is called the container 'disassociates' an instance of the bean implementation (developer-written) with the actual container created EJB ( that typically holds a reference to the developer written bean impl).
    What possible use this will be in case of stateless session ejbs?

    I am sure that since you read the EJB specs, you will figure out a credible if not a convincing answer for the invocation of ejbRemove in your stateless session factory. Pointing out that this factory can be used for a stateful session ejbs will not cut it. Investigate whether the method you included to remove instances from the factory is indeed detrimental to performance and other considerations
  31. Just curious[ Go to top ]

    Mahesh,I see your point. Your feedback was very useful.I'll investigate a little further on this and get back.

     For those of you who have just joined this thread and wondering whats happening here, The current arugument is "Does it make sense to have the recyleService() method" in the above described pattern/utility.
     While we are trying to find answers for this part of the topic, the rest of the pattern/utility still was found useful to many.

    Thanks
  32. Hi all,

    Sorry to deviate from the present discussion of recycleService()...

    Kiran, I take your point of having one-to-one relationships with EJBeans and BDs. I'll think over ..

    I have another question.. So, now there is BD(one-to-one) in place. Kiran's example gave a method call from a local client instantiating the BD. Now, how this BD(normal java class) be accessed by a remote client, since BDs are not bound to the container ?

    kindly suggest.
    Thanks
  33. Hi Viji,

     I am not too sure if your question is related to this pattern. Could you provide more information about the example that you were mentioning.

     If your question is purely related to Business Delegates and its access, could you start a seperate thread in the regular J2EE forum.

    Thanks
  34. Just curious + ejbRemove[ Go to top ]

    Mahesh, I should thank you one more time for your inputs.
     
     Here are a couple of quotes from the book Enterprise JavaBeans by Richard Monson-Haefel

    Begin of quotes
    * Some vendors do not pool statelss instances, but may instead create and destroy instances with each method invocation.

    * When a client invokes one of the remove methods on a stateless session bean's remote or home interface, the method is not delegated to the bean instance. The client's invocation of the method invalidates the stub and releases the EJB object: it notifies the container that the client no longer needs the bean
    End of quotes

    Well, may be most containers have a mechanism of determining such a thing, but I think if we can indicate the container it would always help, as we dont know what the container might do exactly when it is notified in such a situation.

     If someone has still some concerns on whether parts of this pattern makes sense in particular situations, then I would suggsest you to make intelligent decisions based on your scenarios. Well, patterns are afterall, best practices and you could either use part of it or all of it or can combine more than one based on what best addresses your problem context.

    And one more interesting thing that Mahesh has brought up. it will not work in its current form as a factory for statuful session ejbs.
    Yes, it wont. Because it's a StalessFactory. However this leaves me with a question as to why cant we extend this pattern to address the stateful needs as well. At this moment, I feel this pattern can be extended with minor changes to address the stateful beans as well.

    I will soon come up with an extension of the existing pattern. Meanwhile I have a small request for all you wonderful guys with wonderful ideas , please contribute your ideas on extending this pattern.

    Mahesh, I would greatly appreciate any of your comments on extending this. You are indeed giving the right direction.

    Thanks
     Kiran
  35. Travel[ Go to top ]

    Hi guys,

     I will be on travel the next 15 days. Moving to a different country :)

     please keep the thread alive.

    Kiran.
  36. Hi all,

    Just been reading all this. And I was wondering what people's take would be if we were to slap a facade on top of all this. I currently am only using stateless session beans but in the future the application may grow such that we may want to replace/add entity beans. So I was thinking if we had a facade (abstract class) that had all the business method calls. Another class that would extend this facade and make a call to the Factory in order to fulfill all the business methods. Would that work? That way the facade is just business methods. And later down the road if we wanted to have an entity beans, the client code would not have to change.

    Can i get people's thoughts on this. thanks.
  37. Just curious + ejbRemove[ Go to top ]

    Kiran,

    I am not sure if you are understanding the intentions of the writer correctly. Almost all commercial containers pool stateless session beans. Not withstanding that fact, there is absolutely no reason to make a call that removes the reference to the bean instance from the EJBObject as any bean instance can satisfy any request from the client, for statless EJBs. It doesn't make sense to disassociate the reference to the container implemented EJBObject. So you should let your container manage that instead of instructing it to remove the reference for stateless session beans. I am not sure what part of statelessness you don't understand. Let me reiterate one last time, to satisfy a request from a client, an EJBObject can use one of many pooled instances. It doesn't matter which one it is. Once it has a reference to a bean instance, it can typically hold that reference to satisfy later requests. The container determines, based on load, when to return the bean instance to the pool.

    And as far as extending your 'pattern' to stateful EJBs is concerned, as I pointed out before, the core of this is nothing but a basic usage of reflection. In case of stateless session EJBs, there can be only one create method (the one with no-orgs). If the utility method can accept parameters (array of objects) to indicate the actual parameters, the corresponding create method can be invoked on the home instance. However, i have enough self-esteem and not enough time to involve myself with 'extending' this pattern and deluding myself that i am doing something creative.

    Finally, as I said before the patterns section of this site, though very useful to many has given the ability for fairly ridiculous pieces of justifications to create a pattern out of really nothing. They should periodically monitor this section to flush out the pretending patterns from atleast the genuine ones. This will be my last post on this topic.
  38. Just curious + ejbRemove[ Go to top ]

    Mahesh,
     I respect all your final thoughts on this. My intention of posting this pattern here is not to force people to use it by giving false justfications.

     This is just an attempt to share what I have done and I am sure there will be 1000 better ways of doing the same. My main intention was to learn atleast a couple of those many better ways from you guys out there.

     And finally, I agree that serverside should take a look at all the patterns in this section. But instead of flushing out patterns, it might be a better idea if they could comment on pros/cons and possibly give appropriate solutions.

     Well, even I think it is time to put an end to this pattern as I have to attend to a few things in this new country. Will post again(may be on a different topic) if I have something more useful in near future.

    Kiran
  39. I have implemented this nearly one year ago
    and it works just fine. However, I would not
    call this far beyond a service locator. Returning
    a given Base Interface doesn't mean that the
    company's service locator cannot return it.

    The Service Locator could - with little overhead -
    verify the type of service and see if it's a stateless
    session bean and implements the Base Interface and
    then return the object otherwise throw an Exception
    if it is a stateful session bean or entity bean.


    Cheers,

    John