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

Reply via email to