Single Home Interface for All Session Bean

Discussions

J2EE patterns: Single Home Interface for All Session Bean

  1. Single Home Interface for All Session Bean (28 messages)

    Simple Improvement:
    We had 100 SessionBeans.So 3*100=300 total files.
    We could reduce the Number of files to 2* 100+1 =201 by adopting single Home interface and a strategy
    where all Remote extends the parent interface.
    as follows..




    //the single home interface allowing to create ANY session bean.
    public interface TheOnlyHome extends EJBHome {
      public TheRemote create() throws RemoteException,CreateException;
    }

    //The parent remote interface.
    public interface TheRemote extends EJBObject {
    }


    //the remote interface-1

    public interface MyRemote extends TheRemote {
    public void remoteMethod1() throws RemoteException;

    }

    //the remote interface-2
    public interface MyRemote2 extends TheRemote {
    public void remoteMethod1() throws RemoteException;

    }

    public interface YourRemote extends TheRemote {
    public void YourRemoteMethod1() throws RemoteException;
    }

    <session>
    <ejb-name>MyRemoteSession</ejb-name>
          <home>org.vim.TheOnlyHome</home>
          <remote>org.vim.MyRemote</remote>
          <ejb-class>org.vim.bean.MyRemoteBean</ejb-class>
          <session-type>Stateless</session-type>
          <transaction-type>Container</transaction-type>
          ..
          ..
     </session>

    <session>
    <ejb-name>YourRemoteSessiion</ejb-name>
          <home>org.vim.TheOnlyHome</home>
          <remote>org.you.YourRemote</remote>
          <ejb-class>org.you.bean.MyRemoteBean</ejb-class>
          <session-type>Stateless</session-type>
          <transaction-type>Container</transaction-type>
          ..
          ..
     </session>


    //client code
    Object object = ctx.lookup("YourHome");
    TheOnlyHome theHomeForAll =
    (TheOnlyHome)
    PortableRemoteObject.narrow(object,TheOnlyHome.class);

    YourRemote = (YourRemote) theHomeForAll.create();


    I think its a simple improvement.
    Comment.

    Threaded Messages (28)

  2. Why so many beans?[ Go to top ]

    Why do you have so many session beans? Sessions beans are supposed to be coarse grained objects, so to have so many beans I would think you would have to have an enormously large and complicated application.
  3. Why so many beans?[ Go to top ]

    yes,thats true.
  4. A bit confusing![ Go to top ]

    YourRemote = (YourRemote) theHomeForAll.create();
    How does a container decide to create YourRemote object rather that MyRemote object or other objects when you use the above code?
  5. I've written and tested the code (below), for an message-worflow application
    (Process Manager Pattern - see Enterprise Integration Patterns book ) the problem here is to invoke local-ejb services by command messagges, that shows to a MDB (ProcessManager) what local ejb (service) needs to run.

    Regards
    Marduk

    P.S.: When I was compiling the SOAServiceLocalHome, I had a warning that it must return a spacified bean's object (local interface). But following the specification there was not problems.

    CODE: SOA means Software-Oriented Architecture.


    public interface SOALocalService {
    public Class getLocalInterfaceClass();
    }

    public interface SOAServiceTestLocal extends EJBLocalObject, SOALocalService {
    public void someMethod();
    }

    public interface SOAServiceLocalHome extends EJBLocalHome {
    public SOALocalService create() CreateException;
    }

    public class SOAServiceTestBean implements SessionBean,SOAServiceTestLocal {
            ...
    public void someMethod() {
                   ...
    }

    public Class getLocalInterfaceClass() {
    return SOAServiceTestLocal.class;
    }
    }

    public class SOAProcessManagerBean MessageDrivenBean, MessageListener {
            ...
    public void onMessage(javax.jms.Message msg) {
            ...PARSING msg for dynamic parameters
             SOAServiceLocalHome home = (SOAServiceLocalHome)initCtxt.lookup (...DYNAMIC_BUSINESS_JNDI_NAME...);
    SOALocalService local = (SOALocalService)home.create();
    Class serviceClass = local.getLocalInterfaceClass();
    Method[] serviceMethods = serviceClass.getMethods();
    for(int i=0;i<serviceMethods.length;i++){
    if(serviceMethods[i].getName().equals(...DYNAMIC_BUSINESS_METHOD...))
    serviceMethods[i].invoke(local,...DYNAMIC_BUSINESS_METHOD_PARAMETERS);
    }
     }
  6. Not a good idea[ Go to top ]

    I'd rather to use XDoclet.
  7. Use Session Façade and Application Service patterns

    http://www.corej2eepatterns.com/Patterns2ndEd/SessionFacade.htm
    http://www.corej2eepatterns.com/Patterns2ndEd/ApplicationController.htm
  8. I suppose you have to make a clear note that this strategy works for statless sessions (and I would add MDB too) only. This tric is a natural consequence from the common functionality for all stateless session (and MDB homes) - a single stateless create method. Unfortunately the homes for the rest of the EJB component types are component-specific and therefore cannot be unified that easily.
  9. yes.thats true.
    Initially only Statelss Session were in our mind.But as you pointed can be applied to MDB as well.Anyway MDB do not have RemoteInterface.

    Well have gone through SessionFacade,ApplicationService and EJB Command Pattern.
    These are also very good things.But few problems from my perspective :
    1. SameRule for all.
    For example in command pattern,if Stateless Session is acting as CommandExecutor,then Transaction Attribute speicified for executeCommand(aCmd) will be same for all.Meaning finer level of controle is not possibble.
    2.Growing no. of commands or application service classes are equally tough to manage.

    I recalculated..and my application has 60 Session Beans at presetn..can grown in next year at the most to 75..
  10. Too man Bean[ Go to top ]

    These are also very good things.But few problems from my perspective :

    > 1. SameRule for all.
    > For example in command pattern,if Stateless Session is acting as CommandExecutor,then Transaction Attribute speicified for executeCommand(aCmd) will be same for all.Meaning finer level of controle is not possibble.

    I totally disagree with this point. With a proper designed framework using chains of command classes with a configuration file (xml), different transaction settings can be obtained. Obviously you have explored enough of the command pattern before you can come up with an application framework that does this.

    > 2.Growing no. of commands or application service classes are equally tough to manage.

    They are easier to manage than EJB.

    > I recalculated..and my application has 60 Session Beans at presetn..can grown in next year at the most to 75..

    There is a need to review through all your beans. I have come across design that uses one SessionBean for one method which is obvious waste of resources. I don't think any application needs such a big number of EJBs.
  11. Too man Bean[ Go to top ]

    I totally disagree with this point. With a proper designed framework using chains of command classes with a configuration file (xml), different transaction settings can be obtained. Obviously you have explored enough of the command pattern before you can come up with an application framework that does this.

    >
    ok.accepted.this is not then the descriminating factor.

    > > 2.Growing no. of commands or application service classes are equally tough to manage.
    >
    > They are easier to manage than EJB.
    >
    > > I recalculated..and my application has 60 Session Beans at presetn..can grown in next year at the most to 75..
    >
    > There is a need to review through all your beans. I have come across design that uses one SessionBean for one method which is obvious waste of resources. I don't think any application needs such a big number of EJBs.

    We have say N components.Each Component provides 10 or more services on an average.Each component have a session-facade providing access to this set of services to end clients[web-tier/device-tier].

    now using command pattern where each service is implemented by one command,the no.of commands are N*10.
    if N=60 then it surmounts to 600![one can have Switch/Case in single command to reduce no.of classes or can use reflection also.we want to avoid that.suggest any other alternative please if any.]
    We have 60 Session Beans.
    We controll each service attributes differently.
    Each service is managable wrt:
    1. Transaction
    2. Remotability[Local/Remote interface]
    3. Security
  12. instead of extending TheRemote interface for every remote interface, we can directly, return EJBObject in the TheOnlyHome.
  13. instead of extending TheRemote interface for every remote interface, we can directly, return EJBObject in the TheOnlyHome.


    NO ITS NOT REQUIRED.
    Just an asside discussion though.The super interface has advantage of centralizing the services provided by all components.These services are usefull mainly to :
    1. Component Management Services
       - getComponentServices()
       - getComponentServiceExecutionSummary()
       

    2. Services meant for other generalized components like Search
       - search(String entityName,List criterialist)
       - getEntityPage(String entityName)
       
    3. to support strategy pattern for business rule validation
       - getValidator()
       - getValidator(RequestInfo ri)
    4. to support command engine interface
       -executeCommand(Command cmd)
    5.

    Now all session-beans extends the common-super-session-beans centralizing the implementation as-well.
    comment.
  14. YourRemote = (YourRemote) theHomeForAll.create();

    how can a "TheRemote" be casted down to "YourRemote".

    cos, your remote has more information than TheRemote.
  15. It is not a bad idea to reduce the number of files. But i dont see any importance to adapt pattern to reduce number of home interfaces.
  16. This is a Simple Improvement.May not be considered as a PATTERN.
    I am sure many company have architectures where Session Beans are used as Business Service/Business Process Layer.We have such.For such cases i think its important.

    For Architecture using EJB Command pattern this idea is ofcourse useless.
    So it depends on the architecture of application.

    Runtime behaviour, I have not studied though, also i think should be improved as it is the single Class in picture for different session beans.[Well this is still ok..as now a days server have 1GB of RAM normally!!]

    So we can conclude that if the Business Service layer is realized using no_of session beans this idea allows you to reduce Files and to an extent runtime footprint.
  17. I have tried this pattern on my side. I am using Weblogic Server 8.1 SP1 and the following message is coming up:-

    In EJB FirstBean, the return type for the home create method create() must be the bean's remote interface type.

    :-(

    And I believe this is correct, as the create method, in the Home Interface, is returning a Non-Remote Interface.

    Which App server did you try this on ?

    Do you think App servers are handling this differently ?
  18. really?It should.
    Please make sure that the TheRemote is extending the javax.ejb.EJBObject as detailed.::

    //The parent remote interface.
    public interface TheRemote extends EJBObject {
    }


    BTW.I have tested it with Jboss
    > I have tried this pattern on my side. I am using Weblogic Server 8.1 SP1 and the following message is coming up:-
    >
    > In EJB FirstBean, the return type for the home create method create() must be the bean's remote interface type.
    >
    > :-(
    >
    > And I believe this is correct, as the create method, in the Home Interface, is returning a Non-Remote Interface.
    >
    > Which App server did you try this on ?
    >
    > Do you think App servers are handling this differently ?
  19. I also got the same problem as Deepak Nayal when using your pattern. I used EJBLocal instead.

    " The return type for the local home create method create() must be the bean's local interface type"

    I used weblogic 8.0

    Thanks,
    Bo
  20. Not working on weblogic 8.1[ Go to top ]

    I am also getting the same problem of return type of create method. The only difference is that i tried it for local home.
  21. Not working on weblogic 8.1[ Go to top ]

    ohhhh....Hello all again.
    I could test it successfully with jboss-3.2.1_tomcat-4.1.24.But received the same error with Weblogic 8.1 as mentioned by many.
    Now the beheviour of Weblogic is perfectly right:"it is observing following rule of Ejb2.0 specification".

    section 7.10.6 Session bean’s remote home interface:
    • The return type for a create<METHOD> method must be the session bean’s remote interface
    type.

    Though the same does not apply for Local Interface.Atleast i am concluding this from the specification.
    7.10.7 Session bean’s local interface
    The following are the requirements for the session bean’s local interface:
    • The interface must extend the javax.ejb.EJBLocalObject interface.
    • The throws clause of a method defined in the local interface must not include the
    java.rmi.RemoteException.

    • The local interface is allowed to have superinterfaces.


    Secondly regarding Remote Interface also..Jboss behaviour is lenient..but still weblogic is not incorrect either as it observes the spec-rule...

    so conclusion is not to use it unless Component inheritance is standard feature..the ejb2.0 spec is mentioning "Component Inheritance" as a feature for future release..lets wait and see what it really means..!!

    thnx all for their energetic-contribution
  22. Why not[ Go to top ]

    If you use XDoclet, the number of files you would need to maintain is not too much. I do not see any problem with having a lot of session beans, it just means you have a lot of business logic to deal with, which is just a fact of life in a large application.

    But you might want to throw in a few more classes into the mix to collapse some of your session beans into one. ala a facade layer.

    The homes are just factories that create your SLSBs, and its probably easier to leave it with many rather than doing something that may cause incompatibilities with other environments.

    I'm playing around with Maven + XDoclet + Cactus myself and I have found that I do not need to deal with the XML descriptors anymore (except for Cactus testing which just annoys me). I've posted the patches to the maven genapp in http://jira.codehaus.org/ViewIssue.jspa?key=MPGENAPP-6 which provides a sample EJB session facade and CMP complete with Cactus test. Hopefully this would give you some insight on how to use code generators such as xdoclet to do some of the menial work for you.
  23. hello it seems to be good idea....Our thinkings are really making j2ee much robust and modular

    We can also think of a single session bean have Different Action classes according to parameters...
    so that sesssion bean contains different types of execute methods..
    we can make different types of abstract base classes if there are more functions which can have the same parameters..

    one disadvantage in EJB LAYER when compared to servlet(web layer)

    in doGet or doPost we get request and response objects and from the servlet u can get Config and Context variables..

    But when a method is invoke on an ejb..we have to pass the parameters explicitly..





    i am pasting a simple examp

    my ejb action 1
    ---------------
    public abstract class MyEJBAction{

    public abstract ArrayList execute(
    TypeA a,
    TypeB b)
    throws Exception;

    }

    my ejb action2
    -------------

    public abstract class MyEJBDispatchAction{

    protected Class clazz = this.getClass();

    private static String methodNamePrefix = "get";

    protected Class types[] = { TypeA.class };

    public ArrayList execute(
    TypeA a,
    String methodName)
    throws Exception {

    return dispatchMethod(a, methodName);
    }

    protected ArrayList dispatchMethod(
    TypeA a,
    String methodName)
    throws Exception {

    ArrayList result = null;

    Object object = null;

    try {

    if (methodName == null || methodName.equals("")) {
    //INVALID METHOD
    } else {

    methodName = methodNamePrefix + methodName;
    Method method = clazz.getMethod(methodName, types);

    Object args[] = {a};
    result = (ArrayList) method.invoke(this, args);
    return result;
    }
    } catch (ClassCastException cce) {

    System.out.println("cce::"+cce);

    return (null);
    } catch (IllegalAccessException iae) {

    System.out.println("cce::"+iae);
    return (null);
    } catch (InvocationTargetException ite) {

    System.out.println("cce::"+ite);

    Throwable t = ite.getTargetException();
    if (t instanceof Exception) {
    throw ((Exception) t);
    } else {

    return (null);
    }
    }

    return null;
    }

    }

    my factory
    ----------
    public class MyEJBActionFactory {

    private static final String actionPackagePrefix =
    "myPackage.";


    public static String getActionClassName(String methodName) {

    return actionPackagePrefix + methodName + "Action";
    }

    public static MyEJBAction getEJBActionInstance(String actionName)
    throws Exception {
    ArrayList result = null;

    Class klass = null;
    Object object = null;

    if (actionName == null || actionName.equals("")) {
    //INVALID METHOD
    } else {

    String className = getActionClassName(actionName);
    klass = Class.forName(className);
    object = klass.newInstance();


    }

    return (MyEJBAction) object;

    }

    public static MyEJBDispatchAction getEJBDispatchActionInstance(String actionName)
    throws Exception {
    ArrayList result = null;

    Class klass = null;
    Object object = null;

    if (actionName == null || actionName.equals("")) {
    //INVALID METHOD

    } else {

    String className = getActionClassName(actionName);
    klass = Class.forName(className);
    object = klass.newInstance();
    }

    return (MyEJBDispatchAction) object;

    }

    }

    my business interace
    --------------------
    public interface MyBusinessInterface{


    public abstract ArrayList execute(
    TypeA a,
    TypeB b,
    String actionName)
    throws Exception;


    public abstract ArrayList execute(
    TypeA a,
    TypeB b,
    String actionName)
    throws Exception;
    }


    my remote
    --------
    public interface MyRemote extends MyBusinessInterface, EJBObject {

    }

    my home
    -------
    public interface MyHome extends EJBHome {

    MyRemote create() throws RemoteException, CreateException;
    }

    my bean
    -------

    public class MySLBean implements SessionBean, MyBusinessInterface {

    private SessionContext sc;
    private DataSource dataSource;

    public ArrayList execute(
    TypeA a,
    TypeB b,
    String actionName)
    throws Exception {

    ArrayList result = null;
    try {
    MyEJBAction myEJBAction =
    MyEJBActionFactory.getEJBActionInstance(actionName);

    result =
    myEJBAction.execute(a, b);
    return result;

    } catch (Exception e) {

    }
    return null;

    }

    public ArrayList execute(
    Type a,
    String actionName,
    String methodName)
    throws Exception {

    ArrayList result = null;

    try {
    MyEJBDispatchAction myEJBDispatchAction =
    MyEJBActionFactory.getEJBDispatchActionInstance(actionName);

    result =
    myEJBDispatchAction.execute(a, methodName);

    return result;

    } catch (Exception e) {


    }
    return null;
    }

    }


    NB:
    we can choose these kind of pattern only if we r having methods which can take same parameters so we can group them in an action class

    make actual implementation for action class type 1 & 2.

    Use action class Type1 if the business logic (one method-single class)is too heavy ..other wise use action2(dispatch one)
    mail me at joseph @ mastek.com for any clarifications
    www.mastek.com
    Joseph Antony Aruja
    Mastek Ltd.
    Millenium Business Park
    Mhape, Navi Mumbai
          Tel: 5591-4646 Ext:4920
  24. The enterprise bean must not attempt to query a class to obtain information about the declared
    members that are not otherwise accessible to the enterprise bean because of the security rules of the Java language. The enterprise bean must not attempt to use the Reflection API to access
    information that the security rules of the Java programming language make unavailable.

    participate also in : Strategy : Using reflection to invoke EJB.
  25. hi iam not using reflection to invoke any method on ejb object!

    it is inside bean(method) and there is no synchronisation problem

    could u expalian it more...
  26. response to Joseph's query[ Go to top ]

    see my response here
  27. Well...well.

    Are you talking about not having package
    your jars with several Home Interface Classes.

    Well, I suppose that works. However, I agree with
    some comments above.

    First of all, EJBs are supposed to be coarse grained.
    You usually don't need 300 services and deploy those.
    What you can do is use the Session Facade Pattern and
    invoke Local EJB Objects. Makes it a heck of a lot faster
    anyways.
    Second, EJB Components are usually component-based designs
    and not necessarily fully object-oriented. You usually use
    fine-grained objects from within the EJB to qualify for
    Object Oriented Design.
  28. it can't work in jbuilder EJB GUI[ Go to top ]

    it can't work in jbuilder EJB GUI, I have tested it , from jdon.com
  29. As per EJB2.0 specification (EJB 2.0: 6.3.1, 7.8, 7.10.6). WSAD 5 forces to return specific, but not generic remote interface. It was possible with WSAD 4, but not with WSAD 5.

    Example:
    deploy:
         [echo] Deploying EJB JAR file

         [exec] [*Error] /undeployed_Enterprise(Class: com.xxx.yyy.enterprise.services.SsbUserManagerHome): CHKJ2402E: create() must return com.xxx.yyy.enterprise.services.SsbUserManagerRemote (EJB 2.0: 6.3.1, 7.8, 7.10.6).