(Во-первых, это не мой код. Во-вторых, чтобы защитить виновных, я изменил имена классов, чтобы скрыть что-то конкретное для моего работодателя, поэтому, если вещи не соответствуют друг другу, вот почему!).
Может кто-нибудь помочь мне прояснить сомнение, пожалуйста? Меня попросили исследовать проблему с полным пулом соединений, и этот код, кажется, пахнет.
В наших журналах много org.hibernate.SessionException: Session is closed!
вокруг следующего кода, который использует пул соединений, который ведет себя плохо.
Звонки поступают через веб-сервис:
1 @Stateless
2 @WebService(name="MyWebService", targetNamespace="http://www.mycompany.com/2010/01/WebService/myWebService")
3 @WebContext(contextRoot="/myContextRoot", secureWSDLAccess=false)
4 public class MyWebService implements IMyWebService {
6 @WebMethod
7 @NotNull
8 public ArrayList<SearchResult> performSearch(ArrayList<String> criteria) {
9 GetAllResponses caller = new GetAllResponses();
10 return caller.doSearch(criteria);
11 }
13 }
Класс GetAllResponses
выглядит следующим образом:
1 public class GetAllResponses {
2 private static MyHome myHome = new MyHome();
4 public SearchResult doSearch(ArrayList<String> criteria) {
5 return doSearchInternal(criteria.elementAt(0), criteria.elementAt(1));
6 }
8 private SearchResult doSearchInternal(String a, String b) {
9 DataObject info = myHome.findDataObject(a, b);
10 return info.getAsSearchResult();
11 }
12 }
А MyHome
выглядит следующим образом:
1 @Stateless
2 @Local({MyHomeInterface.class})
3 public class MyHome {
4 private Session session;
6 public DataObject findDataObject(String a, String b) {
7 try {
8 this.session = MyHibernateUtil.getSessionFactory().getCurrentSession();
9 Transaction tx = this.session.beginTransaction();
10 //do stuff with session and return a DataObject
11 } catch (Exception ex) {
12 ex.printStackTrace();
13 } finally {
14 this.session.close();
15 }
16 }
18 public DataObject doAnotherFind(String a, String b) {
19 try {
20 this.session = MyHibernateUtil.getSessionFactory().getCurrentSession();
21 Transaction tx = this.session.beginTransaction();
22 //do stuff with session and return a DataObject
23 } catch (Exception ex) {
24 ex.printStackTrace();
25 } finally {
26 this.session.close();
27 }
28 }
30 }
Обратите внимание, как во второй строке GetAllResponses
класс MyHome
создается как статическое поле, а в строках 8 и 20 MyHome
назначено поле session
.
Исходя из моего понимания вещей, SSB MyHome
не управляется сервером J2EE (JBoss 4.2.2 GA), поскольку он был создан как статическое поле класса GetAllResponses
, а не обращен к нему JNDI. Следовательно, два потока могут обращаться к одному и тому же экземпляру MyHome
в одно и то же время, и поскольку сеанс хранится в поле session
, первый вызов может очень легко заменить его Session
другим Session
, что приведет к всевозможные проблемы, включая org.hibernate.SessionException: Session is closed!
в строках 9 и 21 из MyHome
(например, два потока вызывают findDataObject
, первый поток запускает строку 14 сразу после того, как второй поток запускает строку 8 и до того, как он запускает строку 9).
Я прав?