Lets say in an application you have an entity called User. Each User can have many Articles which are loaded using lazy fetching.
@Entity
@Table(name = "Users")
public class User {
private Integer id;
private Set<Article> articles = new HashSet<Article>();
...
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
public Set<Article> getArticles() {...}
}
On the web service end, I want to load a user by Id and pass it to a jersey Viewable JSP to be returned and displayed. I also want to use a single session for every request.
@GET
public Response getUser() {
Session session = getSessionFactory().openSession();
session.beginTransaction();
User user = (User) session.getNamedQuery("getUserById").setInteger("id", 1).uniqueResult();
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("user", user);
Viewable v = new Viewable("/user", dataMap);
Response r = Response.ok(v).build();
session.getTransaction().commit();
session.close();
return r;
}
In user.jsp, I want to access the articles and print them out.
<c:forEach var="a" items="${it.user.articles}">
<span>${a.title}</span>
</c:forEach>
Running this code and trying to request the JSP ends up throwing an exception:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: my.package.User.articles, no session or session was closed
This happens because apparently creating the Viewable, passing it to the ResponseBuilder and calling build() doesn't actually create the JSP. The JSP is created somewhere further down the line, after my method has returned and the session has been closed.
One obvious option would be to set the fetch type for articles to eager, but that's not ideal as in most cases I will not need to load or display the articles when I'm using a User object.
Is there a way to force jersey to interpret and construct the jsp before my method returns? Is there some kind of onResponse or postResponse listener I could pass my code to close the session to?
Is there anything I should be doing differently with the way I'm handling opening/closing hibernate sessions in general? From googling around, one-session-per-request seems to be what most people advocate using so I thought I'd try that.