I would not recommend you to open database sessions in a filter, since there is a high risk that a non authenticated user can run a DOS attack if you do not define your filters in the correct order. Instead I'd recommend to use Google-Guice, stripes-guice and a annotation based interceptor solution using guice-aop stuff. A simple solution would look like this: The interceptor: public class SessionInterceptor implements MethodInterceptor {
private static final Log log = LogFactory.getLog(SessionInterceptor.class); private final FlushMode flushMode; private final Provider<SessionFactory> sessionFactoryProvider; public SessionInterceptor(FlushMode flushMode, Provider<SessionFactory> sessionFactoryProvider) { this.flushMode = flushMode; this.sessionFactoryProvider = sessionFactoryProvider; } @Override public Object invoke(MethodInvocation invocation) throws Throwable { if (log.isDebugEnabled()) log.debug(MessageFormat.format("Intecepting call to {0}.{1}", invocation.getThis().getClass(), invocation .getMethod())); SessionManagedService service = getService(invocation); SessionFactory sessionFactory = sessionFactoryProvider.get(); Session session = sessionFactory.openSession(); session.setFlushMode(flushMode); Transaction transaction = session.beginTransaction(); if(log.isDebugEnabled()) log.debug(MessageFormat.format("Injecting session({2}) before call to {0}.{1}", invocation.getThis().getClass(), invocation .getMethod().getName(), Integer.toString(session.hashCode(), 16))); service.setSession(session); try { final Object ret = invocation.proceed(); if (log.isDebugEnabled()) log.debug(MessageFormat.format("Commiting transaction after call to {0}.{1}", invocation.getThis() .getClass(), invocation.getMethod())); transaction.commit(); return ret; } catch (Exception e) { try { if (log.isDebugEnabled()) log.debug(MessageFormat.format("Rolling back transaction after call to {0}.{1}", invocation .getThis().getClass(), invocation.getMethod())); transaction.rollback(); } catch (Exception e1) { log.fatal("Cannot rollback transaction", e1); } throw e; } finally { try { if (log.isDebugEnabled()) log.debug(MessageFormat.format("Closing session after call to {0}.{1}", invocation .getThis().getClass(), invocation.getMethod())); session.close(); } catch (Exception e) { log.fatal("Cannot close session", e); } service.setSession(null); } } private SessionManagedService getService(MethodInvocation invocation) { final Object ret = invocation.getThis(); if (!(ret instanceof SessionManagedService)) throw new IllegalArgumentException("this inteceptor supports only instances of " + SessionManagedService.class + " but was passed an " + ret.getClass()); return (SessionManagedService) ret; } } The guice module binding: bindInterceptor(Matchers.subclassesOf(UserService.class), Matchers.annotatedWith(ReadOnlySession.class), new SessionInterceptor(FlushMode.MANUAL, binder().getProvider(SessionFactory.class))); bindInterceptor(Matchers.subclassesOf(UserService.class), Matchers.annotatedWith(ReadWriteSession.class), new SessionInterceptor(FlushMode.COMMIT, binder().getProvider(SessionFactory.class))); The service: public class UserService extends SessionManagedService { private static final Log log = LogFactory.getLog(LectureService.class); private final HibernateCRUDService<User> hibernateCRUDService; @Inject public UserService(HibernateCRUDService<User> hibernateCRUDService) { this.hibernateCRUDService = hibernateCRUDService; } @ReadWriteSession @ServiceExceptionIntercepted public void create(User user) throws ServiceException { try { hibernateCRUDService.create(session, user); } catch (ConstraintViolationException e) { log.error(MessageFormat.format("Could not create User {0}", user), e); throw new DuplicateUserNameException(); } } @ReadOnlySession @ServiceExceptionIntercepted public User retrieve(Long id) throws ServiceException { return hibernateCRUDService.retrieve(session, id); } ... } You should also have a look at cp30 connection pooling and make sure that every database contact happens after a transaction was opened by a session.beginTransaction() which is committed or rolled back in any case. Make sure to not use Hibernate built in connection pool! ([ INFO] 21:17:01 org.hibernate.connection.DriverManagerConnectionProvider:64 - Using Hibernate built-in connection pool (not for production use!)) Regards, Richard On Tue, Jun 2, 2009 at 4:50 PM, Morten Matras <morten.mat...@gmail.com> wrote: > Let's start with the questions for you: > > - How do I modify the filter below / use another (downloadable) filter to > get a Hibernate Filter in my application that takes care of transaction > management and commit / rollback for me that works on a windows server and > with an application that uses RedirectResolution? > - I consider switching to Stripernate (or whatever it's called now a days). > Would that be a good idea? > > > In our application http://www.redantenna.com I've added a > HibernateRequestFilter inspired by: https://www.hibernate.org/43.html > > The architecture is something like: (MySQL - Hibernate - Tomcat - JSP) > > In this filter I open a new session on every request and either commit it or > roll it back when the request is finished and the .jsp created and returned. > > This has been working fine for years when deployed on linux machines, but > this application is deployed on a windows machine causing this error: > > java.net.SocketException: No buffer space available (maximum connections > reached?): JVM_Bind > at java.net.PlainSocketImpl.socketBind(Native Method) > at java.net.PlainSocketImpl.bind(Unknown Source) > at java.net.Socket.bind(Unknown Source) > at java.net.Socket.<init>(Unknown Source) > at java.net.Socket.<init>(Unknown Source) > > The application tries to connect to a mysql database (on another server) and > is using a port to do that. When this error occurs nothing but a complete > reboot of the server helps. > > I took a look at the source code of the hibernate filter and found that the > session is never closed (unless that happens behind the scenes in commit and > rollback of the transaction). I tried adding a session.close() to the filter > but that caused errors when using RedirectResolution(...) in the > application. > > ---- > > Source code of the doFilter method in the HibernateRequestFilter: > > public void doFilter(ServletRequest request, > ServletResponse response, > FilterChain chain) > throws IOException, ServletException { > > try { > sf.getCurrentSession().beginTransaction(); > if (! sf.getCurrentSession().isConnected() ){ > > sf.getCurrentSession().reconnect(sf.getCurrentSession().connection()); > } > chain.doFilter(request, response); > } catch (StaleObjectStateException staleEx) { > throw staleEx; > } catch (Throwable ex) { > try { > if (sf.getCurrentSession().getTransaction().isActive()) { > log.debug("Trying to rollback database transaction after > exception"); > sf.getCurrentSession().getTransaction().rollback(); > } > } catch (Throwable rbEx) { > log.error("Could not rollback transaction after exception!", > rbEx); > } > > // Let others handle it... maybe another interceptor for > exceptions? > throw new ServletException(ex); > } > finally{ > Session session = sf.getCurrentSession(); > Transaction transaction = session.getTransaction(); > //doCommit is an internal parameter telling the filter whether it should > commit or rollback. > Boolean doCommit = (Boolean) request.getAttribute("commit"); > if (doCommit != null && doCommit.booleanValue()){ > transaction.commit(); > } > if (transaction.isActive()){ > transaction.rollback(); > } > session.close(); > } > } > > --- > > With the last line: session.close(); the application is not able to handle > RedirectResolution correctly. It causes an error saying that the session is > closed. Without that the application get's the "maximum connections > reached?" error causing the server to stop working. > > > > > -- > Morten Matras > Consultant > Blob Communication ApS > Svendsagervej 42 > DK-5240 Odense NØ > P: (+45) 76 6-5-4-3-2-1 > W: www.blobcom.com > E: morten.mat...@gmail.com > > ------------------------------------------------------------------------------ > OpenSolaris 2009.06 is a cutting edge operating system for enterprises > looking to deploy the next generation of Solaris that includes the latest > innovations from Sun and the OpenSource community. Download a copy and > enjoy capabilities such as Networking, Storage and Virtualization. > Go to: http://p.sf.net/sfu/opensolaris-get > _______________________________________________ > Stripes-users mailing list > Stripes-users@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/stripes-users > > ------------------------------------------------------------------------------ OpenSolaris 2009.06 is a cutting edge operating system for enterprises looking to deploy the next generation of Solaris that includes the latest innovations from Sun and the OpenSource community. Download a copy and enjoy capabilities such as Networking, Storage and Virtualization. Go to: http://p.sf.net/sfu/opensolaris-get _______________________________________________ Stripes-users mailing list Stripes-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/stripes-users