Hibernate session in RequestFactory

746 views
Skip to first unread message

rwiatr

unread,
Mar 27, 2011, 4:47:23 AM3/27/11
to Google Web Toolkit
Hello,
I have a problem with RequestFactory and Hibernate session.
[hibernate.LazyInitializationException] - failed to lazily initialize
a collection of role: app.server.dao.HierarchyImpl.children, no
session or session was closed

@OneToMany(cascade = CascadeType.ALL)
@JoinTable(name = "HIERARCHY_RELATE", joinColumns =
{ @JoinColumn(name = "parent_id") }, inverseJoinColumns =
{ @JoinColumn(name = "child_id") })
public Set<HierarchyImpl> getChildren() {
return children;
}

public static List<HierarchyImpl> rootHierarchyRequest() {
int i = 0;
try {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
List<HierarchyImpl> hList = new ArrayList<HierarchyImpl>(session
.createQuery("from Hierarchy where parent is null").list());
session.close();
return hList;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Adding FetchType.EAGER helps but in long terms will not solve my
problem.
Is there a good way to manage Hibernate session by RequestFactory?

Nooonika

unread,
Mar 27, 2011, 10:20:05 AM3/27/11
to Google Web Toolkit
Try: Hibernate.initialize(hList);

rwiatr

unread,
Mar 27, 2011, 2:27:01 PM3/27/11
to Google Web Toolkit
Thanks for the response Nooonika.
Unfortunately it doesn't work for me. I'm looking for a mechanism to
open a session before request is processed and close after (or
something like that).
Here's something that works, at least for now.

public class SessionRequestFactoryServlet extends
RequestFactoryServlet {
private static final ThreadLocal<Session> perThreadSession = new
ThreadLocal<Session>();

@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException
{

perThreadSession.set(HibernateUtil.getSessionFactory().openSession());
try {
super.doPost(request, response);
} finally {
perThreadSession.get().close();
perThreadSession.set(null);
}
}

public static Session getPerThreadSession() {
return perThreadSession.get();
}
}
in the DAO object:
@Transient
public static List<HierarchyImpl> rootHierarchyRequest() {
try {
Session session = SessionRequestFactoryServlet
.getPerThreadSession();
List<HierarchyImpl> hList = new ArrayList<HierarchyImpl>(session
.createQuery("from Hierarchy where parent is null").list());
return hList;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
And a servlet entry in web.xml
<servlet-class>app.server.requestfactory.SessionRequestFactoryServlet</
servlet-class>

RequestFactoryServet uses ThreadLocal variables so I guess it's ok.
Anyone knows a more suitable way to achieve this? I don't have any
experience with such thing and I'm afraid it can cause much more
problems in the future. Anyone has any suggestions?

Ann Smith

unread,
Mar 27, 2011, 4:36:58 PM3/27/11
to google-we...@googlegroups.com

I think filters were designed for this kind of  job 
Have you seen this?
http://stackoverflow.com/questions/4988397/gwt-requestfactory-how-to-use-single-entitymanager-per-request


--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.


Kevin Anderson

unread,
May 19, 2011, 1:53:11 PM5/19/11
to google-we...@googlegroups.com
If you are using spring to provide your services, just add this to your web.xml:

<filter>
       <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
       <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
   </filter>
   <filter-mapping>
       <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>

Magno Machado

unread,
May 19, 2011, 2:55:05 PM5/19/11
to google-we...@googlegroups.com
Look at guice and guice-persist

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.



--
Magno Machado Paulo
http://blog.magnomachado.com.br
http://code.google.com/p/emballo/

bond

unread,
Aug 13, 2012, 11:07:43 AM8/13/12
to google-we...@googlegroups.com
Hi guys,
I'm using request factory with single Hibernate session per request using FilterServlet implementation as described here http://stackoverflow.com/questions/4988397/gwt-requestfactory-how-to-use-single-entitymanager-per-request.
These are the two classes:

public class ThreadLocalHibernate
{
    private static ThreadLocal<Session> holder = new ThreadLocal<Session>();

    private ThreadLocalHibernate()
    {
    }

    public static Session get()
    {
        return holder.get();
    }

    public static void set(Session session)
    {
        holder.set(session);
    }
}

public class PersistenceFilter implements Filter {
    protected static final Logger log = Logger.getLogger(PersistenceFilter.class.getName());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // Avvia Hibernate
        MyHibernateUtil.getSessionFactory();
    }

    @Override
    public void destroy() {
        // Ferma Hibernate
        MyHibernateUtil.getSessionFactory().close();
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        Session session = MyHibernateUtil.getSessionFactory().getCurrentSession();
        ThreadLocalHibernate.set(session);
        try {
            // Inizia la transazione
            session.beginTransaction();
            chain.doFilter(req, res);

            // Chiude la transazione
            session.flush();
            session.getTransaction().commit();

        } catch (Throwable ex) {
            log.error("", ex);
            try {
                if (session != null && session.getTransaction() != null && session.getTransaction().isActive()) {
                    session.getTransaction().rollback();
                }
            } catch (RuntimeException rbEx) {
                log.error("Non riesco ad annullare la transazione.", rbEx);
            }
            String message = "";
            if (ex.getCause() != null)
                message = ex.getCause().getMessage();
            else
                message = ex.getMessage();

            throw new IOException(message);
        }
    }
}

I can't send to the clients exceptions that are rised in doFilter() methods of PersistenceFilter. In fact many errors are launch only when the row session.getTransaction().commit() is run. So actually I see an error in the server but on the client I see a success message.

Thanks for your help

Best regards
To unsubscribe from this group, send email to google-web-toolkit+unsub...@googlegroups.com.

Thomas Broyer

unread,
Aug 13, 2012, 5:53:42 PM8/13/12
to google-we...@googlegroups.com
Session != transaction.

You're supposed to use a single session per request but one transaction per service method.

bond

unread,
Aug 14, 2012, 3:09:16 AM8/14/12
to google-we...@googlegroups.com
Hi Thomas,
I know that a session is different from a transaction. But in my case I need also a single transaction per request in order to manage correctly the lazy entity with hibernate.
The problem is that I can't send error message to the client when the error is on PersistenceFilter.

Any ideas?

Thanks

Thomas Broyer

unread,
Aug 14, 2012, 11:13:55 AM8/14/12
to google-we...@googlegroups.com
You're trying to solve the wrong problem. If you have an issue with lazy loading, then load eagerly, do not extend your transaction lifetime.

bond

unread,
Aug 15, 2012, 6:57:02 PM8/15/12
to google-we...@googlegroups.com
Hi Thomas,
thanks for your reply. My problem is not use or not use a Filter to solve this problem. My problem is try to send exception caugth in PersicensteFilter on the client. I need a per request session and transaction.
If my problem was only lazy inizialization of course this method is not necessary. I've many entity with complex fields and when I persist, RF calls automatically findById that raise org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session. So I need that when I call a method on RF all go in a unique session and transaction.

Thanks very much

Daniele

bond

unread,
Aug 26, 2012, 5:51:53 AM8/26/12
to google-we...@googlegroups.com
Hi guys,
any ideas about my question?

Thanks very much

Thomas Broyer

unread,
Aug 26, 2012, 6:55:56 AM8/26/12
to google-we...@googlegroups.com


On Thursday, August 16, 2012 12:57:02 AM UTC+2, bond wrote:
Hi Thomas,
thanks for your reply. My problem is not use or not use a Filter to solve this problem. My problem is try to send exception caugth in PersicensteFilter on the client. I need a per request session and transaction.
If my problem was only lazy inizialization of course this method is not necessary. I've many entity with complex fields and when I persist, RF calls automatically findById that raise org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session. So I need that when I call a method on RF all go in a unique session and transaction.

If you cannot retrieve the same object twice in the same session (but different transactions), then fix that.
As an alternative, you can also override the isLive method of your Locators so that it doesn't rely on find().

But I reiterate my first answer: you're looking at the wrong problem.

bond

unread,
Aug 26, 2012, 8:20:20 AM8/26/12
to google-we...@googlegroups.com
Hi Thomas,
I already override isLive method and I return always true.

I can't understand if is possibile to create an Exception and send it to the client from the class PersistenceFilter. Forgetting for a moment the question of how I manage sessions with Hibernate, I would like to know how I can raise and send an exception to the client from the PersistenceFilter class ie outside the context of the request.

Thanks for your patience

Thomas Broyer

unread,
Aug 26, 2012, 10:08:49 AM8/26/12
to google-we...@googlegroups.com


On Sunday, August 26, 2012 2:20:20 PM UTC+2, bond wrote:
Forgetting for a moment the question of how I manage sessions with Hibernate, I would like to know how I can raise and send an exception to the client from the PersistenceFilter class ie outside the context of the request.

You have two choices:
  • Return anything but a 200 status code, to trigger a "request transport error" on the server-side (handled by the RequestTransport on the client-side; it's generally used for authentication, as in the Expenses and Mobile Web App samples for instance)
  • Send back a "general failure" message. Use the MessageFactory AutoBeanFactory to create the message and AutoBeanCodex to serialize it. The message should consist of a ResponseMessage with a non-null generalFailure ServerFailureMessage. The other properties can (should) be null. The ServerFailureMessage properties map directly to the ServerMessage properties passed to the onFailure of the various Receivers.
Reply all
Reply to author
Forward
0 new messages