Thursday, April 28, 2016

Using Hibernate 5.0.1 with Vaadin 7

Sources:

Sources for the fixes: 
In Vaadin 7 the Application class was replaces with the UI class. Instead of configuring the web.xml, VaadinServlet can be used with the proper annotations.
Instead of transaction listeners, servlet filters can be used to intercept the request and manage the session.

The following is gpiercey's implementation that is updated for Hibernate 5.0.1

Interceptor

@WebFilter(urlPatterns = { "/*" }, dispatcherTypes = { DispatcherType.REQUEST, DispatcherType.FORWARD,
  DispatcherType.INCLUDE, DispatcherType.ERROR })
public class SessionInterceptor implements Filter
{
 private static final ApplicationLogger logger = new ApplicationLogger(SessionInterceptor.class);

 @Override
 public void init(FilterConfig filterConfig) throws ServletException
 {
  logger.executionTrace();
 }

 @Override
 public void destroy()
 {
  logger.executionTrace();
  final Session session = DatabaseUtil.getSessionFactory().getCurrentSession();

  if (session.getTransaction().getStatus() == TransactionStatus.ACTIVE)
   session.getTransaction().commit();

  if (session.isOpen())
   session.close();
 }

 @Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
   ServletException
 {
  final Session session = DatabaseUtil.getSessionFactory().getCurrentSession();

  try
  {
   if (session.getTransaction().getStatus() != TransactionStatus.ACTIVE)
    session.beginTransaction();

   chain.doFilter(request, response);

   if (session.getTransaction().getStatus() == TransactionStatus.ACTIVE)
    session.getTransaction().commit();
  }
  catch (StaleObjectStateException e)
  {
   logger.error(e);

   if (session.getTransaction().getStatus() == TransactionStatus.ACTIVE)
    session.getTransaction().rollback();

   throw e;
  }
  catch (Throwable e)
  {
   logger.error(e);

   if (session.getTransaction().getStatus() == TransactionStatus.ACTIVE)
    session.getTransaction().rollback();

   throw new ServletException(e);
  }
 }
}

Database Util

public class DatabaseUtil
{
    private final static ApplicationLogger logger = new ApplicationLogger(DatabaseUtil.class);
    private final static SessionFactory sessionFactory;
    private final static String CONFIG = "/path/to/hibernate.cfg.xml";

    static
    {
        try
        {
            logger.trace("Initializing DatabaseUtil");
            
            /**
             * 
             */
            sessionFactory = new Configuration().configure(CONFIG).buildSessionFactory();
            
        }
        catch (Throwable e)
        {
            logger.error(e);
            throw new ExceptionInInitializerError(e);
        }
    }

    public static SessionFactory getSessionFactory()
    {
        logger.executionTrace();

        if (sessionFactory.getCurrentSession().getTransaction().getStatus() != TransactionStatus.ACTIVE)
            sessionFactory.getCurrentSession().beginTransaction();

        return sessionFactory;
    }
}

Hibernate Configuration

Current session context property has to be added to the Hibernate Configuration:
<property name="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</property>

Maven Dependencies

The following repository and dependencies were used:
<repository>
<id>vaadin-addons</id>
    <url>http://maven.vaadin.com/vaadin-addons</url>
</repository>

<dependency>
    <groupId>org.vaadin.addons</groupId>
    <artifactId>hbncontainer</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.1.0.Final</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.21</version>
</dependency>

Usage

Now for database calls from the WebApp you can use the followings:
final Session session = DatabaseUtil.getSessionFactory().getCurrentSession();
final Transaction transaction = session.getTransaction();

Exaple: UI and VaadinServlet class

@SuppressWarnings("serial")
@Theme("mytheme")
public class MyUI extends UI {

        @WebServlet(value = "/*", asyncSupported = true)
 @VaadinServletConfiguration(productionMode = false, ui = MyUI.class)
 public class MyServlet extends VaadinServlet {}

        @Override
 protected void init(VaadinRequest request) {

  final VerticalLayout layout = new VerticalLayout();
  layout.setMargin(true);
  setContent(layout);

  TextField message = new TextField();
  message.setCaption("Type your message here:");
  Button writeButton = new Button("Write to database");
  writeButton.addClickListener(new Button.ClickListener() {
   @Override
   public void buttonClick(ClickEvent event) {

    getNewSession().save(new Message(message.getValue()));

    layout.addComponent(new Label("Written to database."));
   }

  });

  Button readButton = new Button("Read from database");
  readButton.addClickListener(new Button.ClickListener() {
   @Override
   public void buttonClick(ClickEvent event) {

    List<Message> result = getNewSession().createQuery("from Message").list();
    for (Message msg : result) {
     layout.addComponent(new Label(msg.getId() + " " + msg.getText()));
    }

    layout.addComponent(new Label("Read from database."));
   }
  });

  layout.addComponents(message, writeButton, readButton);
 }

 private Session getNewSession() {
  return DatabaseUtil.getSessionFactory().getCurrentSession();
 }
}

No comments:

Post a Comment