问题
Related to this question (where the answer doesn't really get to the point):
Hiberate with Struts2 - Use Full Hibernate Plugin or another method to close Sessions?
I have the same setup: Struts 2.2.3 and the struts2-fullhibernatecore-plugin-2.2.2-GA . I have none of the defaults changed for Struts2 and for the Plugin. I'm using MySQL, no additional connection pooling, and nothing fancy in general.
I use the following code in my Action:
FeedGroup persistent = null;
List<FeedGroup> list = objectList = (List<FeedGroup>) session.createCriteria(FeedGroup.class)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.list();
if (feedgroup.getId() != 0) // a new one
{
persistent = (FeedGroup) session.get(FeedGroup.class, id);
}
if (persistent != null)
{
persistent.copyValuesFromOther(feedgroup);
session.update(persistent);
}
else
session.save(feedgroup);
return list;
This gives me the following exception only in about every 10 cases or so, which doesn't happen in my code, but likely after the transaction got committed by the plugin.
org.hibernate.SessionException: Session is closed!
org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:72)
org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1346)
abelssoft.newspaper.actions.ActionHelper.prepare(ActionHelper.java:65)
com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:167)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:190)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:498)
org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
java.lang.Thread.run(Thread.java:619)
Is it a problem in the logic of my code or is it a problem related to the Plugin? If the latter, can a configuration change help? I'd like to use the plugin as it is, I'm just worried that it doesn't work reliably or that my understanding of Database stuff is too primitive and that my code needs rewriting ;-).
回答1:
Okay, as noone's got an answer, I looked into the question and the code again and googled a bit.
Fact 1: The plugin is only supported till Struts 2.1.6, additionally I'm using the new Tomcat 7, so I guessed that something might just not work with the plugin.
Fact 2: Someone in a Hibernate Forum pointed out, that this problem can arise if you try to access the session instead of opening a new one: Hibernate Forum:Session is Closed! (solution near the bottom)
It seem that fact 1 lead to the Annotations of @session
and @transaction
not working correctly, or I was using them wrong, as they were often null in my prepare method, which is such a class and from which all my struts2 actions are derived:
public abstract class ActionHelper extends ActionSupport implements Preparable, ...
In this class, I used the following Annotations that usually worked in all other projects so far (Struts 2.1.6 and Tomcat 6):
@SessionTarget
Session db;
@TransactionTarget
Transaction transaction;
private FeedGroupDAO _feedGroupDao;
In the prepare method, I had defensive programming code that checked if the session was null and then replaced it by the current hibernate session. The problem was that this session was often times closed, what you can find out if you ask if (!session.isOpen())
Therefore now I use the following code in my prepare method in the ActionHelper class:
public void prepare() throws Exception {
// initialize DAO Objects with Session and Transaction
if (session == null)
{
session = com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.getNewSession();
if (!session.isOpen())
throw new NullPointerException("Fix the code: session's not here");
transaction = session.beginTransaction();
}
_feedGroupDao = new FeedGroupDAO(session,transaction); // init more DAOs with the same session/transaction
The getNewSession()
method of the plugin seems to use Hibernate's openSession()
internally, therefore this seems to be the working solution from the Hibernate-forums. Additionally, this still supports the OpenSessionInView pattern as the struts2-fullhibernate-plugin is managing the session and transaction you got from the static getNewSession()
method. As a sidenote, I try to move away from defensive programming to throwing exceptions as soon as possible ;-)
Hope this could help you.
来源:https://stackoverflow.com/questions/6294764/struts2-full-hibernate-plugin-session-is-closed