Before any DBUnit tests can be run, there must be some expected data, some manipulation and then comparison with some expected results. This posting will look at the setup of the initial data and loading the expected data sets. The next post will look at filtering and comparing results with expected results.

Setup of initial data

To setup the initial data set, the method getDataSet needs to be overridden. Here is an example implementation:

This loads an XML file containing data to be used as the initial data set. This can mimic an existing database table state, so if the actual database has 3 rows, this XML could have the same 3 rows. The data set returned can then be used in the tests for comparisons.

The easiest way to manipulate the data sets is via XML files.

Setup of expected data

For the unit tests to be effective, it is useful to have some expected data set to compare the results of a test run. DBUnit allows you to setup the expected data set for comparison of results.

The expected data set is setup in the same way as the initial data set described above. Here is some code that shows the expected data set being loaded from an XML file:

DBUnit is a very good tool for use in testing Hibernate applications in the data access layer. DBUnit based tests work by comparing the state of the database from particular method calls and comparing with an expected data set. If the data sets match with the database data state, then the test is said to be successful.

Fortunately, using DBunit is straightforward and powerful tests and comparisons can be done.

To cleanly implement DAOs in the data access layer where the Hibernate persistence takes place, it is a good idea to have interfaces to abstract entry into this layer so that new implementations can be swapped in and out without affecting any of the other layers in a layered application architecture.

Google has some packages that take the abstraction further where a DAO can be used against a single specified domain object (such as a Hibernate entity class). The interface to extend so that all these features are available is com.googlecode.genericdao.dao.hibernate.GenericDAO and this interface should be extended in the DAO interface package.

As this DAO interface extends the GenericDAO<X, Y> interface, when implementing the DAO interface, the save(), find(), etc methods will pass in parameters that are of the type X value in the generic, so they become save(X), find(X), etc. These method declarations in the interface can be overridden too to provide specific functionality.

It is a good idea to have a BaseDao class that all subclasses will extend from. The base class can contain a validator that checks objects of any type before they are persisted to the database. The BaseDao class should extend GenericDAOImpl class as this class extends HibernateBaseDAO so all session handling can be done.

As you can see, the overridden method will validate the entity before persistence. Any errors will be flagged and no persistence takes place. The validator and session factory are injected in as needed.

To make use of the BaseDao and the interface mentioned above, these need to be used in a DAO bean class that contains concrete methods to do something useful such as providing services like checking if an email exists or saving a phone number but also using the added functionality that the BaseDao and the interface brings along with it.

As you can see, both the BaseDao and the interface are implemented to allow other implementations to be used too. All of the goodness that the BaseDao and the inteface brings can also be used. In this case, methods such as find(Address a), save(Address a), remove(Address a), etc can also be used in addition to the user service defined methods.

When implementing entities in Hibernate, sometimes some validation needs to be done on the data that the entities will hold. For example, a postal code needs to be a certain length and format, a phone number cannot contain letters and need to be a certain length. In Hibernate/JPA this is possible through the use of several validation annotations and their properties. Some of the common ones are as follows:

@Size(max=10, message="{email.type.size}")

This annotation limits the size of the data being set in the entity. If it is outside of the size constraints then an appropriate message is displayed during validation failure.

@NotNull(message="{email.address.notEmpty}")

This annotation ensures that the data being set in the entity is not null. If it is null, then an appropriate message is displayed during validation failure.

Notice that the messages are reading some property from a properties file. It has been set this way for internationalisation and so that the messages can be changed without redeployment of the application. To use a properties file, create a properties under src/main/resources directory so that it is read in from the classpath. The properties file needs to have key value pairs, the key must match the message name value in the annotation.

A project that incorporates Hibernate is pretty straightforward to setup as long as the Spring Framework is used in conjunction with it. This example assumes Spring and Maven will be used. To setup Hibernate, follow these steps:

4) Add a new configuration properties file into the same directory src/main/resources and call it <project_name>.properties:

The usual Hibernate configuration parameters such as the dialect, to show SQL, the hbm2ddl settings can be added in here too or separated to another properties file. I have separated it into another file for convinience and placed it in the same directory as the Hibernate configuration file. The contents of this file are:

The Hibernate settings will be picked up by the SessionFactory from a Spring configuration file and all properties will be injected in. This allows one Hibernate settings file holding common properties but separates the properties that are different for each environment.

5) Configure Spring to read in these properties files to setup the Hibernate SessionFactory

For Hibernate to work, the session factory it uses needs to be setup via Spring. To do this, add the following into the Spring application context XML file:

An entity class can have many named queries where HQL (Hibernate Query Lanuage) can be used to manipulate the particular table(s) stored in the database. Each named query must have a unique name and can be accessible anywhere in an application to be called.

@Id

Id is a special annotation that uses fields in a class to highlight them to be treated as IDs.

@GeneratedValue

This annotation is usually paired along with the @Id annotation and means that the unique identifiers are auto generated by Hibernate.

@Column(name="columnName", nullable=false, length=99)

Each field in an entity can correspond to a column, where a column name, length and whether the column can be null can be specified.

@ManyToMany(cascade=cascadeType.PERSIST)

This annotation means that the association will be many to many between two entities and that an intermediate table needs to be setup between the two entities to handle the relationship. This intermediate links the two entities together and has relationship of many-to-one and one-to-many respectively. The cascade type of PERSIST means that do not persist the entire object map each time a save is done, only on the change entity itself. A cascade type of ALL would do the entire object tree persistence.

Tables that are generated can be joined to create a new table that holds joined columns and foreign key columns. A unique constraint can be added to a column to join so that one of the sides of ‘Many’ becomes ‘One’. InverseJoinColumn means the other side of the ManyToMany association.

Sometimes, a unique data type is needed to hold information about certain pieces of data, such as phone type, address type. A new data type can be created and associated with a column by using the Hibernate @Type annotation as shown above.

Where to place the annotations?

Annotations such as those listed above should be placed in the POJO Entity class’ getter methods. Sometimes, some of the validations and annotations listed above do not work correctly if the annotations are declared at field level.

I have recently been studying the Hibernate tutorials to understand Hibernate better in the projects I have been working with. Unfortunately, the tutorial as is does lead you down a blind alley in a few cases, nothing major, but can leave you tearing your hair out as it’s assumed you would know how to make the applications work!

The last section of chapter 1, where you create an EventManagerServlet, the tutorial says:

That seems all well and straightforward, but when you issue the Maven command it builds a JAR file! To make it build a WAR, simply modify the Maven POM file, so that:

<packaging>jar</packaging>

is changed to:

<packaging>war</packaging>

As easy as that! Now you have a WAR file under the target folder of the project.

The next issue was that when deploying to Tomcat, the default application would not start due to a ClassCastException and/or in the startup logs, Tomcat complains that there is a conflict in the servlet API JAR. This is because the servlet-api dependency declared in the Maven POM file is bundled in with the tutorial application thus causing this conflict. To prevent the JAR from being bundled in but still referenced under NetBeans so the project still compiles, simply add the following:

This post shows a simple example of how to call EJBs deployed on one server (in this case JBoss AS) from a different server (Glassfish AS). This example is useful because in some cases, EJBs are called from different remote servers in truly distributed applications.

Firstly create an enterprise project called JBoss5EEApp. Also create an EJB module called JBoss5EEApp-ejb. Create a stateless session bean called HelloBean, has a single business method called sayHello that takes in a string parameter and returns a string message.

Once the EJB has been created, it should like as follows under NetBeans

Simple EJB project

Deploy it onto the JBoss AS by right clicking the EAR project and clicking Run, this will deploy and start the application on the server.

Now that the EJBs are ready and running, it is time to create the client to be run on the Glassfish server. Firstly, create a new web application under NetBeans and set the target server to point to the Glassfish server. Call the project GlassfishWebApp.

The EJB module contains source for the EJB and it’s remote interface, in this case called HelloBeanRemote. Copy the package and this remote interface into the web project for Glassfish. Now create a new servlet called CallBeanServlet, place it in a package com.riz.web.clients. The package structure should now look as follows.

Glassfish web project

The code for the processRequest method within the servlet should be as follows:

Notice that the lookup points to the JBoss server settings. One important thing to do is to set the classpath to include the JBoss AS client JARs and the EJB module project JAR. Add these JARs to the project and tick each of them to be packaged in the WAR that will be generated except for the EJB module project JAR. Leave only that one unticked.

Once this step has been done, deploy the project onto the server by right clicking the web project on the NetBeans IDE and selecting the Run option. This will deploy and run the application on the Glassfish server.

The example should run and call the HelloBean EJB from the JBoss AS side and return the result as shown.

Result from calling the JBoss AS EJB

Note that the HelloBeanRemote interface has to be included in the web project source so that the casting is done correctly when the EJB call is looked up from the Glassfish server, otherwise a ClassCastException will be thrown.

Another cast exception that can be thrown during the lookup is if the EJB has not been correctly deployed on the JBoss server. Ensure that EJBs are deployed correctly before running the Glassfish client. To ensure EJBs are correctly deployed, they can be viewed via the JMX console under JBoss. Under NetBeans, click on the Services window, expand the servers tree node, right click the JBoss AS node and select the View JMX Console option. Once the JMX console has appeared in the web browser, on the left hand side, select the jboss.j2ee link in the list of links and on the main right hand side, the EJB projects should all be listed including the HelloBean module and its associated JAR file as shown.

JBoss AS JMX console

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/package com.riz.web.clients;

This post shows a simple example of creating a simple stateless EJB that has two business methods. One generates a random number, between zero and one, and the other method takes a single parameter that will generate a number between zero and that number.

Under the NetBeans IDE, create a new Java EE Enterprise Application project, give it a name, set the location and click Next.

Set the server as JBoss Application Server, Java EE version 5 and create an EJB module with the name RandomNumber-ejb and click Finish.

A new project appears on the Projects list as shown below.

New EJB Project

Right click on the RandomNumber-ejb project, and

Select new Session Bean

Give it a name of RandomNumber and a package name

Set it to Stateless

Select the Local and Remote checkboxes

Click Finish

A new EJB appears in the list called RandomNumber. Open this in the source editor.

Create two new methods,

findNum that takes no arguments and returns a double

findNumInRange that takes a double as an argument and returns a random double between 0 and that number.

To create a method and ensures it gets promoted to the Remote interface

Right click in the source editor

Select Insert Code…

Select Add Business Method…

A dialog box appears to enter the method name, parameters and return types.

Once implemented, right click on the EAR project and select Clean and Build… and then deploy it by selecting the Deploy option. JBoss will deploy the EJB and make it available as shown in the logs:

The web services that are deployed on the server can be browsed by pointing to the jbossws context root, http://localhost:8080/jbossws (your port number should be changed if different to default 8080).

JBoss deployed web services

Notice that the WSDLs can be browsed for each web service that is deployed. The RandomNumber web service has now been deployed and is present on the list of services. A web service client now needs to be implemented to make use of this deployed service.