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();
 }
}

Monday, April 25, 2016

Setting up H2 database connection in Eclipse Luna in a Maven project

Sources:

Download the H2 Database Engine

  • Open the pom.xml of your project >
  • add H2 database engine as a dependency.
For this tutorial version 1.4.191 was used.
Maven repository: http://mvnrepository.com/artifact/com.h2database/h2
To download it, right-click on the Project Name in Eclipse Project Explorer > Maven > Download Sources

Download Eclipse DTP (Data Tools Platform)

  • In Eclipse, go to Help > Eclipse Marketplace... > 
  • search Data Tools Platform > 
  • click Install > 
  • select both Extender SDK and Enablement Extender SDK > 
  • accept licence agreement > 
  • wait patiently until a popup informs you that the installation was successful and Eclipse needs to be restarted.

Open the "Database Development" perspective

This perspective was installed with the DTP.
  • In Eclipse, go to Window > Open Perspective > Other... > Database Development 

Add Database Connection

  • In the Database Development perspective, in the Data Source Explorere, right-click on Database Connections > New... >
  • select Generic JDBC and enter a Name for the connection then click Next >
  • select H2 Driver from the list of drivers.
  • if the list is empty, click New Driver Definition button >
    • on the Name/Type tab, click Generic JDBC Driver and give it a unique Driver Name.
    • on the JAR list tab, click Add JAR/Zip... > select H2 JAR file from Maven repository > click Open.
    • on the Properties tab, enter a Database Name for the database, and the following:
      • Connection URL - jdbc:h2:~/test
      • Driver Class - org.h2.Driver
      • User ID - sa
    • click OK.
  • click Test Connection to see that the connection works.
  • click Finish.
Now you can connect to the database by right-click on the name > Connect.
Once you connected you can edit the tables by right-click on the table name > Data > Edit

Connect to the Database

To connect to a database, a Java application first needs to load the database driver, and then get a connection. A simple way to do that is using the following code:
import java.sql.*;
public class Test {
    public static void main(String[] a)
            throws Exception {
        Class.forName("org.h2.Driver");
        Connection conn = DriverManager.
            getConnection("jdbc:h2:~/test", "sa", "");
        // add application code here
        conn.close();
    }
}

Create a new Database

By default, H2 creates a new database on the first connection, if the one with the specified name does not exist.
After the  jdbc:h2: prefix a path to the database can be given. The ~/test creates a new test database in the user's home directory.