I dint know stripersist but I think it is a hibernate solution similar
to grails and other RAD solutions. The proposed solution is not a
solution like stripersist. It introduces a new layer in your
application. So in order to store a user, stripes is only used as web
component, doing request parameter mapping, validation and event
management. It calls then the service layer and the service layer
stores the user in a database. So you'll have to do more than save()
and commit / rollback. I wrote a simple helper class doing the basic
crud stuff:
public class HibernateCRUDService<T extends PersistentObject> {
        private final Class<T> clazz;

        public HibernateCRUDService(Class<T> clazz) {
                this.clazz = clazz;
        }

        @SuppressWarnings("unchecked")
        public T retrieve(Session session, Long id) throws 
EntityNotFoundException {
                T ret = (T) session.get(clazz, id);
                if (ret == null)
                        throw new EntityNotFoundException();
                return ret;
        }

        public void create(Session session, T persistentObject) {
                session.save(persistentObject);
                session.flush();
        }

        public void update(Session session, T persistentObject) {
                session.update(persistentObject);
                session.flush();
        }

        public void delete(Session session, Long id, Long version) throws
EntityNotFoundException {
                // NOTE this is to work around
                // 
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2792
                // where not-null-constraints are checked when calling delete
                T sessionPersistentObject = retrieve(session, id);
                session.evict(sessionPersistentObject);
                sessionPersistentObject.setVersion(version);
                session.delete(sessionPersistentObject);
                session.flush();
        }

Every service is using this component, so the user uservice is doing
the following:
@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();
                }
                
        }

Notice that the service only takes care of specific exceptions that
will lead to a specific error message the user gets displayed. All
other exceptions are handled using a exception interceptor:
public class ServiceExceptionInterceptor implements MethodInterceptor {
        private static final Log log =
LogFactory.getLog(ServiceExceptionInterceptor.class);

        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
                try {
                        return invocation.proceed();
                } catch (ServiceException e) {
                        throw e;
                } catch (Exception e) {
                        Class<? extends Object> invokedClass = 
invocation.getThis().getClass();
                        String invokedMethodName = 
invocation.getMethod().getName();
                        String paramString = 
buildParamString(invocation.getArguments());
                        log.error(MessageFormat.format("Unexpected exception 
invoking
{0}.{1}{2}", invokedClass, invokedMethodName,
                                        paramString), e);
                        throw new ServiceException();
                }
        }

        private String buildParamString(Object[] arguments) {
                StringBuilder sb = new StringBuilder("(");
                for (Object object : arguments) {
                        sb.append(String.valueOf(object)).append(", ");
                }
                sb.append(")");
                return sb.toString();
        }
}
Notice that this one only handles exceptions which are not an instance
of serviceException since these exceptions are meant to reach the web
layer.

If you need to do more complex things like searches or complex update
and delete operations which can not be done using constraints you'll
do this in a separate service method.

IMHO this enables easy testing of actionBeans and services(eg.
database operations) and helps to keep the actionBeans clean. If the
app grows its easy to separate the web part to another machine and use
the service layer over a web service framework like hessian. It also
makes it possible to divide the development into web and service
development so the work can be striped over more than one developer.

Since I dont know stripersist in detail I'm interested in the
documentation of stripersist. Googled it but without any luck. Can
someone provide a link?

Let me know if the 3-tier way is something you want to use and you
have further questions,
Richard
On Wed, Jun 3, 2009 at 1:22 PM, Morten Matras <kodekon...@gmail.com> wrote:
> Hi Richard
>
> This sounds like a good and solid solution. Could you provide more info
> regarding this.
>
> I have no experience with guice, so I'll need some extra information
>
> 1) How do I set it up with an existing stripes / Hibernate application? Your
> example seems to be an example making it possible to retrieve and save User
> entities. What I'm looking for is something that works as smoothly as
> stripernate where all entities are automatically binded and where all I have
> to do is to save() and commit / rollback.
>
> Please provide a little extra information.
>
> Thanks
>
> Morten Matras
>
>
> 2009/6/2 Richard Hauswald <richard.hausw...@googlemail.com>
>>
>> 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
>
>
>
> --
>  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