-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: Session management via UNC binding
PostPosted: Fri Sep 10, 2004 2:13 pm 
Beginner
Beginner

Joined: Mon Aug 16, 2004 6:09 am
Posts: 46
Location: Geneva, Switzerland
Steve,

UNC binding as it in jboss-head doesn't work properly.
For example, servlet being called twice simulaneosly (so executed in 2 threads) always accessed last session being bound to jndi.

Just to note: I implemented this a little differently so did't encounter this issue. Will publish my version a little later (I need to prepare it) - now just how to reproduce this bug.

Create servlet like this (with hibernate session filter, of course)


Code:
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            Session session1 = HibernateContext.getSession("java:/hibernate/SessionFactory");
            System.out.println("POINT1 thread: "+Thread.currentThread()+" session: "+session1);
            Thread.sleep(60000);
            Session session2 = HibernateContext.getSession("java:/hibernate/SessionFactory");
            System.out.println("POINT2 thread: "+Thread.currentThread()+" session: "+session2);

}


Call it from different browser windows near simultaneosly (so the second thread started before Thread.sleep(60000) ended.)

You'll get:


Code:
19:38:12,996 INFO  [STDOUT] POINT1 thread: Thread[http-0.0.0.0-8080-Processor22,5,jboss] session: net.sf.hibernate.impl.S
essionImpl@156f1b0
19:38:15,340 INFO  [STDOUT] POINT1 thread: Thread[http-0.0.0.0-8080-Processor25,5,jboss] session: net.sf.hibernate.impl.S
essionImpl@52ce2a
19:38:22,996 INFO  [STDOUT] POINT2 thread: Thread[http-0.0.0.0-8080-Processor22,5,jboss] session: net.sf.hibernate.impl.S
essionImpl@52ce2a



As you see servlet executed in first thread at POINT2 got session not the same like at POINT1 but the same like thead2 at POINT1.

It just overrides the same ENC.

after that, you'll see exception during second thread's lookup at POINT2: (because first thread just called unbind against it).

Code:
19:38:22,996 DEBUG [FilterInterceptor] Cleaning up after filter execution
19:38:23,011 INFO  [HibernateContextHelper] Unbinding Hibernate session from scoped bind [java:/hibernate/SessionFactory]
19:38:23,011 DEBUG [HibernateContextHelper] Completed unbinding
19:38:25,340 ERROR [HibernateContext] Unable to locate current session
javax.naming.NameNotFoundException: SessionFactory not bound
        at org.jnp.server.NamingServer.getBinding(NamingServer.java:495)
        at org.jnp.server.NamingServer.getBinding(NamingServer.java:503)
        at org.jnp.server.NamingServer.getObject(NamingServer.java:509)
        at org.jnp.server.NamingServer.lookup(NamingServer.java:282)
        at org.jnp.server.NamingServer.lookup(NamingServer.java:256)
        at org.jnp.server.NamingServer.lookup(NamingServer.java:256)
        at org.jnp.server.NamingServer.lookup(NamingServer.java:256)
        at org.jnp.server.NamingServer.lookup(NamingServer.java:256)
        at org.jnp.server.NamingServer.lookup(NamingServer.java:256)
        at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:530)
        at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:644)
        at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:509)
        at javax.naming.InitialContext.lookup(InitialContext.java:347)
        at org.jboss.hibernate.session.HibernateContext.lookupSessionWrapper(HibernateContext.java:71)
        at org.jboss.hibernate.session.HibernateContext.lookupSessionWrapper(HibernateContext.java:53)
        at org.jboss.hibernate.session.HibernateContext.lookupSession(HibernateContext.java:44)
        at org.jboss.hibernate.session.HibernateContext.getSession(HibernateContext.java:39)

....


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 10, 2004 2:33 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
Yes I am aware of this. Have been talking to the JBoss experts to get their take on this for the past 2 days. This is a difficult issue to solve.

Sure post your code and I'll take a look. But I'll guess that there is one very important use-case that your stuff is not considering that I *need* to solve correctly as I will venture a guess that it will be by far the more common use case. It is a web component calling into an ejb component and both needing to share the same session (ENC not shared between the two containers) for lazy loading during render ala the "Open Session In View" pattern.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 13, 2004 7:31 am 
Beginner
Beginner

Joined: Mon Aug 16, 2004 6:09 am
Posts: 46
Location: Geneva, Switzerland
Steve,

here's how my JNDI binding was different so it didn't encounter this problem.

Instead of binding to ENC concrete UUID, I created the reference as object factory:

Code:
public class ContextBinder {
    private static final Logger log = Logger.getLogger(ContextBinder.class);

    public static void bind(final SessionContext sessionContext) throws NamingException {

        RefAddr refAddr = new RefAddr("hibernateSession") {
            public Object getContent() {
                return sessionContext.getSession();
            }

        };

        Reference ref = new Reference("net.sf.hibernate.Session",
                refAddr,
                HibernateObjectFactory.class.getName(),
                null);

        ((Context) new InitialContext().lookup("java:comp/")).bind("HibernateSession", ref);

    }

    public static class HibernateObjectFactory implements ObjectFactory {

        public Object getObjectInstance(Object ref, Name name, Context nameCtx, Hashtable environment) throws Exception {
            return ((Reference) ref).get("hibernateSession").getContent();
        }
    }

}



Session context instance KNOWS about both jndiName AND scope - so it can pick session from proper storage
(session or thread local). (This was based on your very first implementation of SessionContext.)

As you see - sessionContext.getSession() is called at runtime (jndi lookup) so scope local storage
gives correct session according to scope.


Code:
public class SessionContext
{
   private static Logger log = Logger.getLogger(SessionContext.class);

    private Scope scope;
    private String jndiName;

   private static ThreadLocal threadLocal = new ThreadLocal()
   {
      protected Object initialValue()
      {
         return new Hashtable();
      }
   };

   private static TransactionLocal transactionLocal = new TransactionLocal()
   {
      protected Object initialValue()
      {
         return new Hashtable();
      }
   };

   /* package */
   SessionContext(String service, String scopeName) throws HibernateException
   {
      this(service, Scope.resolve(scopeName));
   }

    public Session getSession(){
        return (Session) getSessions().get(jndiName);
    }

   private Hashtable getSessions()
   {
      if(scope == Scope.THREAD)
      {
         return (Hashtable) threadLocal.get();
      }
      else
      {
         return (Hashtable) transactionLocal.get();
      }
   }

......................

}



Let me see how it is fit into usecases you mentioned...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 14, 2004 7:27 am 
Beginner
Beginner

Joined: Mon Aug 16, 2004 6:09 am
Posts: 46
Location: Geneva, Switzerland
steve wrote:
I *need* to solve correctly as I will venture a guess that it will be by far the more common use case. It is a web component calling into an ejb component and both needing to share the same session (ENC not shared between the two containers) for lazy loading during render ala the "Open Session In View" pattern.


Steve could you clarify the use case I quoted above? It seems like contradiction to your previous post (in this thread http://forum.hibernate.org/viewtopic.php?t=933927) where your said it was baaad:

steve wrote:
But in your scenario and description, these would need to be seperate Sessions. I say this because if you mean the same session, then stuff done in the ejb would be under JTA, but stuff done in the servlet would not be under JTA; this is baaaaad! You are correct, a Session is essentially a unit-of-work; having part of that UOW under JTA control but not other parts is not good.



Well, with my implementation - if servlet & ejb interceptors declare scope="thread" - then if servlet calls ejb they both will get the same session instance. Is this what you mean? The same story appears to be for transactional scope.

Anyway, if we made call from servlet to ejb how can we rely on having a single session? EJB always can be located in different container and there's only transaction who can initiate correct session cleanup.

In Open Session in View pattern there's nothing about calling ejb's. Using thread scope we do have a single session shared between servlets and jsp's which belong to a single request.

Buy the way, I still don't understand what "thread" scope means for ejbs. Could your clarify yor use case which doesn't fit into implementation I published above? (which is just slightly different of yours).
I mean servlet with scope xxx calling ejb with scope xxx and then forwarded to jsp xxx and which of that components you want to share the same session.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.