Hi Larry,

That was a great email!

jc

John Crupi
Senior Enterprise Java Center
SunPS Java Center

----- Original Message -----
From: LAURENCE CABLE <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Wednesday, March 24, 1999 5:06 PM
Subject: Re: Servlets -> EJB Session Persistence


>> My question is how do I maintain session state when using HTML, Servlets
and
>> EJB's?
>>
>> Scenario:
>> 1) An HTML client(view) invokes a servlet. 2) The servlet(controller)
calls an
>> EJB Session bean (Model). 3)The Servlet sends a response back to the
client and
>> terminates. The HTML client invokes the servlet to do something
>> else, and so on.
>>
>> Question:
>> 1) How do you maintain a reference to the Session Bean once the Servlet
>> destroy() method is called?
>>
>
>        Hi Mike,
>                Good question, let me try to give you some guidance!
>
>        This is actually a very interesting problem to solve due the
>interaction
>        of Servlet lifecycle and EJB semantics, and one that we are working
on
>        for the Java2 Platform Enterprise Edition Application Programming
>Model.
>
>        Let's start by restating your problem; how does one persist
>SesssionBean
>        reference(s) across Servlet instance lifecycles?
>
>        Although you do not state it I presume that we are dealing with a
>STATEFUL
>        SessionBean, since if it were STATELESS I would probably recommend
that
>        (going slightly off topic here) you simply obtain and cache the
>appropriate
>        EJBHome interface to the SessionBean class as follows:
>
>                - in a static class variable in the Servlet class
>                        - lives for as long as the Servlet Class is loaded
>                          (this is implementation dependent)
>                        - per Servlet Class
>
>                - in an instance variable in the Servlet
>                        - lives for as long as the Servlet instance
lifecycle
>                          (init() -> destroy())
>                        - at least one per instance
>
>                - in the ServletContext using {set|get}Attribute()
>                        - lives as long as the ServletContext
>                          (this is also implementation dependent)
>                        - at least one per ServletContext
>
>                - in the HttpSession using {put|get}Value()
>                        - lives as long as the HttpSession
>                          (until it is invalidated or the session times
out)
>                        - at least one per HttpSession
>
>        and re-create an instance each time Servlet.service() is called,
>although
>        one could argue which is more efficient, to re-create, or to hold
onto
>the
>        object reference itself, I believe the appropriate usage is to
>re-create
>        since by definition (in the spec) a STATELESS SesssionBean has no
>conversational
>        state.
>
>        (back on topic now)
>
>        Given that we have a STATEFUL SessionBean we cannot/do not want to
>re-create it
>        for every invocation of Servlet.service(). Furthermore, since both
a
>particular
>        Servlet instance lifecycle may be shorter than that of the
HttpSession,
>and that
>        the HttpSession itself may expire, we need to be able to preserve
the
>reference
>        across both Servlet and HttpSession lifecycles.
>
>        In order to preserve the SessionBean across a Servlet instance's
>lifecycle I recommend
>        that you try the following (which is of course greatly simplified
for
>clarity):
>
>        class ExampleServlet implements HttpServlet {
>
>                // ...
>
>                public void doPost(HttpServletRequest req,
HttpServletResponse resp)
>throws ... {
>                        HttpSession session = req.getSession(true);
>
>                        ShoppingCart scart = null;
>
>                        if (session.isNew()) { // it's a new session create
the session bean
>...
>                            ShoppingCartHome scartHome = ...; //
lookup/obtain the Remote
>EJBHome via JNDI
>
>                            scart = scartHome.create(...); // create
instance of shopping
>cart ...
>
>                            session.putValue("ShoppingCart", scart); //
save it in the
>HttpSession
>                        } else {
>                            scart =
(ShoppingCart)session.getValue("ShoppingCart");
>                        }
>
>                        // use the shopping cart ...
>                }
>
>                public void doGet(HttpServletRequest req,
HttpServletResponse resp)
>throws ... {
>                        // same strategy as doPost() ...
>                }
>
>                // ...
>        }
>
>        Now there is one problem with this ... what happens when the
>HttpSession times out, or
>        in otherwise invalidated ... well then we need to preserve the
instance
>elsewhere.
>
>        One approach would be to save it as a client cookie ... as follows:
>
>        class BetterExampleServlet implements HttpServlet {
>
>                // ...
>
>                public void doPost(HttpServletRequest req,
HttpServletResponse resp)
>throws ... {
>                        HttpSession session = req.getSession(true);
>
>                        ShoppingCart scart = null;
>
>                        if (session.isNew()) { // it's a new session create
the session bean
>...
>
>                            // first we look to see if the client already
has a Serialized
>Handle to the
>                            // SessionBean stroed as a cookie?
>
>                            Cookie cookies    = req.getCookies();
>                            Cookie beanCookie = null;
>
>                            for (int i = 0; i < cookies.length; i++) {
>                                if (cookies[i].getName() ==
"EJBHandleCookie") {
>                                    beanCookie = cookies[i];
>                                    break;
>                            }
>
>                            if (beanCookie != null) { // previously encoded
...
>                                String encodedHandle =
beanCookie.getValue();
>
>                                // obtain the encoded serialized handle to
the SessionBean
>                                // from the previously created client
cookie.
>
>                                // use a mythical BASE64 decoder to decode
the encoded value into
>                                // a byte array ....
>
>                                byte[] buf  =
ABase64Decoder.decodeAsByteArray(encodedHandle);
>
>                                // ignoring the appropriate try blocks for
clarity ...
>
>                                ByteArrayInputStream bais = new
ByteArrayInputStream(buf);
>                                ObjectInputStream    ois  = new
ObjectInputStream(bais);
>
>                                scart =
((Handle)ois.readObject()).getEJBObject(); // may fail ...
>
>                                // if the object referenced by the handle
does'nt exist anymore then
>                                // we'll have to re-create it ... this is
problematic since we have
>                                // probably lost state due to an EJB server
failure ...
>                            }
>
>                            if (scart == null) { // no existing object ...
>                                ShoppingCartHome scartHome = ... ; //
lookup/obtain the
>Remote EJBHome
>
>                                scart = scartHome.create(...); // create
instance of shopping
>cart ...
>
>                                // now save the bean as a cookie ...
>
>                                // ignoring the appropriate try blocks for
clarity ...
>
>                                ByteArrayOutputStream baos =
newByteArrayOuputStream();
>                                ObjectOutputStream    oos  = new
OutputOutputStream(baos);
>
>
oos.writeObject((Serializable)scart.getHandle());
>                                oos.close();
>                                baos.close();
>
>                                // use a mythical BASE64 encoder to encode
the serialized handle as
>                                // a string ...
>
>                                String encodedHandle =
>ABase64Encoder.encodeAsString(baos.toByteArray());
>
>                                resp.addCookie(new
Coookie("EJBHandleCookie",encodedHandle));
>                            }
>
>                            session.putValue("ShoppingCart", scart); //
save it in the
>HttpSession
>                        } else {
>                            scart =
(ShoppingCart)session.getValue("ShoppingCart");
>                        }
>
>                        // use the shopping cart ...
>                }
>        }
>
>        I've done a little hand waving here for the sake of brevity but I
>believe that the idea
>        is sound, I hope this helps!
>
>
>        - Larry Cable,
>          Senior Staff Engineer,
>          Java Enterprise Technologies,
>          Sun Microsystems Inc.

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff EJB-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".

Reply via email to