Discussions

J2EE patterns: Pattern Pattern what pattern ?

  1. Pattern Pattern what pattern ? (15 messages)

    This problem almost stumped me, because it almost had me declare the home Interface and the remote interface as session variables in JSP (and I did not know how to do that either). And I needed some way of reusing the remote interface to the stateful session object so the workflow could be captured across multiple JSPs.

    I found a solution through what i call an "Adapter Pattern". A simple java class with a constructor that performs a JNDI lookup gets the home interface and the remote interface for the stateful session bean. The Remote reference, Home reference and the jndi context are member variables to the class. Also each of the method in the remote interface of the stateful session is wrapped into a member method of the Adapter class. So now we had a simple java class that could be used in JSP as follows:

    <jsp:useBean id="adpt" class="com.bkpd.utils.adapters.AdapterPM" scope="session"/>

    <%
    try {
    String str = new String (request.getParameter ("ticketNo"));
    if (adpt.start (str)) { //this invokes remote method of the stateful EJB
    response.sendRedirect ("UserInfo.jsp");
    } else {
    response.sendRedirect ("login.jsp");
    }
    }
    catch (java.lang.reflect.UndeclaredThrowableException ute){
    Throwable t = ute.getUndeclaredThrowable () ;
    t.printStackTrace();
    }
    %>
    Every page that needed the same copy of the stateful session bean simple has to have the first line of <jsp:useBean…/>, followed by the scriplets invoking the remote methods wrapped in the new adapter class you have created just for this. Declaring the scope session helps in reusing the same stateful session bean across multiple JSPs. So now, to build a shopping cart and login functionality into your web application, all you need to do is build a stateful session bean with the functionality and write an adapter around the bean and use the adapter in the JSP ;) How simple is that?

    But my questions to one and all are

    1. Is the pattern name (adapter) correct? Or am i just reinventing the wheel here ?
    2. How is it solved else where (using J2EE from multiple JSP) ?

    Just dont bring up servlets as i dont write any servlets. :)

    Threaded Messages (15)

  2. Pattern Pattern what pattern ?[ Go to top ]

    I think it can be fitted into Business Delegate pattern but for stateful session bean rather than stateless session bean.
  3. Pattern Pattern what pattern ?[ Go to top ]

    Passing the Remote reference as a session variable:

    You can associate an object with a session. So why not pass the remote-interface reference of for example a CustomerBean between the JSPs.
    CustomerBean is a stateful session bean. Once you have the customerID as an integer, you can create a CustomerBean, one for each customer.

    <%@ page import="com.company.yourproject.workflow.*" %>
    <%@ page session="true" %>

    <%
    javax.naming.Context context = new javax.naming.InitialContext();
    Object ref = context.lookup("Customer_JNDI");
    CustomerHome home = (CustomerHome)javax.rmi.PortableRemoteObject.narrow(ref, CustomerHome.class);
    Customer customer= home.create(customerID);
    session.setAttribute("Customer",customer);
    %>

    Now the session Attribute Customer is set to the remote-interface customer of CustomerBean. The following JSP pages can simply get this Customer-Remote-Interface Reference just with one line of code :

    <%
    Customer customer=(Customer)session.getAttribute("Customer");
    %>

    now let the Bean work.

    <%
            customer.doSomething();
            customer.doSomethingElse(xy);
    %>


    Cookies must be enabled in your browser, otherwise it will not work.
  4. Pattern Pattern what pattern ?[ Go to top ]

    The advantage of using a business delegate pattern over using session variable is:
    1. you don't have to write try-catch pair when you call remote object in your jsps
    2. since the exception handler has been encapsolate in delegate java bean, it is easier to maintain and more robust.
    3. you can store some variables in the delegate bean as cache, reduce expensive EJB calls.
  5. Pattern Pattern what pattern ?[ Go to top ]

    Thats a great idea. I did not think a remote reference to EJB could be stored in a session variable. Funny huh? Great idea. Thanks.
  6. Pattern Pattern what pattern ?[ Go to top ]

    Watch out though, if your remote object dies and the reference is invalidated then you need to get a new one. i.e. you need all the exception handling and recreation of remote object etc etc.

    Handling the state changes for all of this within each JSP can be a pain, better to wrap in a java object.

    Jonathan
  7. Pattern Pattern what pattern ?[ Go to top ]

    Remote interfaces should be assumed not to be thread safe, which means simply putting a reference to it in the session may be a bad idea. If two concurrent request are sent to the server by the same user (session) then it is very difficult to prevent concurrent use of resources in the session.

    Also be aware that concurrent requests from the same session are difficult to predict - even if your application doesn't use frames. For example, if a user hits the submit button on a page twice before the first request finished processing.

    I have heard that a business delegate can be used to perform synchronization of access to a remote interface. I'm not positive if this is completely safe, because objects that go in the session may be serialized (for example, in a cluster) so the business delegate that is retrieved from the session will be a copy of the one that went in. This would mean that the condition variable used to perform synchronization may also be a copy.

    Any thoughts?
  8. Pattern Pattern what pattern ?[ Go to top ]

    I did use a delegate pattern instead of the session variable. Now the question is how to make a delegator synchronized ? Are u saying that we should synchronize the reference itself ? Or the Variables(objects) held by the Session Variable (we might use the stateful session object to store some state). So multiple threads dont mess around there?

    Any ideas?

  9. Pattern Pattern what pattern ?[ Go to top ]

    I think you do not need to worry about the concurrent invoke on the stateful session bean.

    please refer http://www.theserverside.com/resources/article.jsp?l=SOAP-EJB4

    it said " If we made a mistake and gave two different clients the same instance of the bean and both clients tried to concurrently invoke a method then the container would stop the second guy to the race and throw an exception. Only one thread of execution is allowed at one time on a stateful session bean."

    So what we need to do is to write a robust catch block in our business delegator.
  10. Pattern Pattern what pattern ?[ Go to top ]

    I would agree with that. The designers of the EJB spec were definitely thinking about this. There is really no simple way to synchronize invocations, so they chose to be optimistic. I imagine they chose not to synchronize/block on the server side for performance reasons.

    Still, what kind of code would you put in your "robust catch block"? Would you attempt to execute your method again?


    quote from EJB Spec 2.0
    ---------------------------------------------------------
    7.11.8 Non-reentrant instances
    The container must ensure that only one thread can be executing an instance at any time. If a client request arrives for an instance while the instance is executing another request, the container may throw the java.rmi.RemoteException to the second request if the client is a remote client, or the javax.ejb.EJBException if the client is a local client. [6]

    Note that a session object is intended to support only a single client. Therefore, it would be an application error if two clients attempted to invoke the same session object.

    One implication of this rule is that an application cannot make loopback calls to a session bean instance.
  11. Pattern Pattern what pattern ?[ Go to top ]

    Yes. quoting from EJB Spec makes it more confirmative.

    As to "robust catch block", what I mean depends on the situation.

    In some situation I think, it is proper to retry the call after some pause. It is better for the client to get a delayed response than a error message.

    And we can try alternative way of complete the method in some cases, such as send message to Message driven bean and inform the client his/her request can not be processed now but definitely process later.

    And we can write the errors to log files if necessary or send the administrator e-mails, thus help to make the system better.

    can't imagine we put these codes in each JSP files.
  12. Pattern Pattern what pattern ?[ Go to top ]

    I found article talking about a proxy class (delegator) in which all methods making calls to EJB are simple synchornized.

    http://java.sun.com/blueprints/guidelines/designing_enterprise_applications/ejb_tier/qanda/


    Check the example that is in the Pet Store

    http://java.sun.com/blueprints/code/jps11/src/com/sun/j2ee/blueprints/petstore/control/web/ShoppingClientControllerWebImpl.java.html
  13. Pattern Pattern what pattern ? (what fun)[ Go to top ]

    Without a doubt, using a business delegate in front of your remote interface is a great idea. Synchronizing it is good to.

    But...

    Once you put this object into the session and get it back out, you are running the risk of getting a clone of the original object. You may not even be on the same physical machine anymore if you are running a cluster. Your session may have been serialized and deserialized. You have no guarantee that the mutex that your business delegate is using is the same as the one some other thread is using. If you are using two different locks, it isn't possible to guarantee mutual exclusion.

    As Leo has said, your business delegate needs to be able to deal with the RemoteException that will inevitably be thrown (Murphy's Law) if your application is storing remote interfaces in the session. All a user would have to do to cause this is click on a submit button several times before a page loads.

    To the point...

    Consider these two possible solutions

    1) If you have a consistent way of dealing with the RemoteException (say - wait half a second and retry) then if might not be bad to define an InvocationHandler that implements this logic, and use dynamic proxys to implement your business delegates. If you are using a business interface (business methods are defined in an interface that the remote interface extends), you can create a dynamic proxy that implements that (the business interface) and proxies to your actual remote interface. Fun.

    2) If you want to keep things simple, you can keep references to your remote interfaces as members of your servlet that implements SingleThreadModel. Any half decent application server will create a pool of these servlets, as well as protect them from the oh so scary world of concurrency. You would obviously want to write some cleanup code (remove the EJBs) in the servlet's destroy method - however I wouldn't bet on it getting called.
  14. Pattern Pattern what pattern ? (what fun)[ Go to top ]

    ok - did that too. Works fantastico.

    I am facing this problem. I run Tomcat 4.0 and JBoss2.4.3

    Now when i rebuild or modify a EJB, restart my EJB server (JBoss).This makes the Delegator loose its reference to the EJB it was holding. But since tomcat doesnt know the EJB server restarted and the remote references it is holding is null or has no object in the JBoss table - how do i get around this problem ?

    Is it possible to sync the delegator (a java class)on Tomcat with session scope and the Stateful session bean on JBoss. Has anyone encountered this problem ?








  15. Pattern Pattern what pattern ? (what fun)[ Go to top ]

    This is a good reason to use a business delegate to access your remote interface. If your delegate receieves a RemoteException it can go back to JNDI, get a new remote interface, and then try the call again.
  16. Stateful Session Beans suck[ Go to top ]

    I hope I'm not the only one here to point this out, but Stateful Session Beans are very bad things. Figure out how to do what you need to do with Stateless Session Beans. There are known limitations on Stateful Session Beans (you can find these all over the web), but it's the unknown (well, unadmitted) limitations that will kill you ... like the fact that when you deploy a Stateful Session Bean into the container of one of the two major vendors, the server crashes regularly without a whimper, a whine or a log trace.