One of my colleagues asked me recently to help him with building and configuring a simple web application with support of Spring IoC and JPA. Application should serve as a simple platform for testing and its only goal is persisting and reading of several entities. He wanted to learn how to add new services, how to write JUnit tests etc.
So instead of usual RTFM I decided to create a tutorial describing how to create such application and how to interconnect particular layers. There are for sure many ways how to achieve this goal and here is one on them. Source of the application is available here. This article does not contain all source files in order to keep the size on a reasonable level. So I describe here only parts which I consider interesting.
Application structure and Maven
Maven is a great tool for managing java-based projects. Having a common directory layout allows us to easily build WAR or EAR archives, generate documentation, run tests and others without complicated configuration. Very easy is also a 3rd party dependencies management. For example adding a dependency on junit is just a matter of following code:
And that’s all we need to define. And if junit has any dependency (so called transitive dependencies), then if would be detected by Maven and these are downloaded into a local repository as well. The complete description of Maven is out of the article’s scope.
Now we use the maven-archetype-webapp arechytepe in order to create a basic layout of thejsp application. Install Maven if you haven’t done it before and use the following command
Maven created a new directory
spring-helloworld containing a base directory layout of our application. To compile and build it call:
A newly created subdirectory
target contains the final package
spring-helloworld.war. Maven can also help us to deploy the application into the web container Tomcat. Let’s add the maven-cargo plugin’s configuration into the Maven configuration file
and two properties definition
then use the plugin to download, install and start Tomcat container with our application.
server should be running, you can check it at http://localhost:8080/spring-helloworld.
Tomcat is installed into to a Maven working directory
target so nothing is being installed into any system directory and therefore we don’t need any administrator access rights.
Import into Eclipse
I usually prefer the Eclipse development environment so I’m going to use the maven-eclipse-plugin in order to create an eclipse project out of our Maven one. As far as I know there is also a similar plugin for IntelliJIDEA. NetBeans is able to use Maven projects natively. So for Eclipse execute this command:
and import as an external project.
Employee and management beans
Let’s create an entity describing an employee, entity management bean responsible for an entity persistence and a simple class containing methods managing access to list of employees, called usually directly from the UI layer.
Entity Employe contains all employee’s attributes and a primary key ID. For an ID is ideal usage of the UUID, but the problem is that the only easy to use UUID generator is the one defined by the
annotation from Hibernate. And that’s not the cleanest solution as we should use the pure JPA interface and not to stick to a implementation specific feature. But for now let’s keep the code simple and define the entity.
The class is annotated by
@Entity defining that the class is a JPA entity. Annotation
@Table defines the DB table used for the table persistence.
To keep the example easier we skip the DAO layer, which is usually used as an intermediate between a business logic and a database layer. Using the JPA is anyway reducing the need to define a DAO layer even for a real production application. In our case will all entity realed operations be managed by the class
. I recommend to have a look on it right now. I’m just going to explain used annotations:
@Repositoryis used to mark classes working with an entity manager and Spring expects translation of
. It also marks the class to be available for the autowiring strategy.
variable will contain an instance of the
@Transacrtionaldeclares that the method will be executed within a transaction. Without additional parameters will be connected to already running transaction or creates a new one in case when there isn’t any transaction running.
Next class is
a class from UI layer. Or said in better words, this class might be part of the UI layer if the architecture is created this way. I decided to define it to have the application designed consistently by independent layers and to be able to present a dependency injection feature. In this case is the attribute
injected by Spring as declared by annotation
@Autowired. In general is an autowire strategy not a best practice, but we can use it to understand how Spring dependency injection works in a real application.
Spring and its configuration
The java code of our application is ready so let’s do some configuration.First we need to add dependencies on several Spring components, HyperSQL database, Hibernate and several other libraries which our application is using. For the complete definition have a look into the
pom.xml file at the
<dependencies> element content.
The Spring context configuration is located in the file
src/main/resource/spring/helloworldContext.xml. Maven is able to put the file into the proper directory of the final package. Let’s go through interesting parts of the configuration:
This element defines a java package where all classes annotated by
@Repository are collected into a list. And every bean from this list can be injected using an annotation
@Resource. For example let’s have a look on the
class and it’s attribute
Configuration of the
is the single configuration point for the JPA implementation. So changing of the persistence layer implementation to eg. Oracle TopLink is as easy as configuring this one property.
The datasource definition. We are going to use the– a database engine written completely in java.Our configuration will use the memory mode which does not need any additional settings. The engine creates a database when first client connects to it and all data is lost after the database is closed. could be of course also configured to use the file based database.
Spring transaction manager. This one is not usually called directly from an application code. We are going to make an exception in our junit tests mentioned later on.
Every method annotated by
@Transactional will be executed within a transaction.
Spring bean definition. Spring creates an instance of the
class and assigns an ID to it. This bean is used for the
servlet implementation. We are using the autowire strategy so there is no need to declare manually all beans in the context. Spring does it for us if we annotate these by
The main part of the application is ready so let’s verify that everything works as expected by creating unit tests. Maven could help us here again. All test classes located in the directory
src/test/main are automatically compiled end executed before every build – unless this step is explicitly skipped. This approach guaranties that the build can succeed only if all test passed successfully.
Our test are going to write into database and afterwards read the content. Written records could influence results of other tests or other application components in a real application. One possible solution is to open a transaction right before the test starts and call a rollback after a test is finished. So we create the abstract class
used as a parent class of all our tests and annotate it by
containing a path to the Spring context configuration. This parent class will contain methods for beginning and closing transactions.
The test class is extending
. All test methods are public and annotated by
@Test. Test body should be clear from the source so will just explain the transaction handling part:
The transaction is created at the beginning of the method and is marked as rollback-only. This means that if the method runs without exception and the transaction is finished successfully (commit) and also if an exception was thrown, the transaction will always be finished by the rollback operation. It means that database will be restored to the status before transaction.
Tests can be executed by:
The test logging output including SQL statements generated by Hibernate are written into console. And test results can be found in the
The next step is creating a simple UI for our application. We create a servlet and one jsp page. The page displays list of all employees and a form to insert a new employee into a database. The employee list is in the
and passed into
via a request attribute. Jsp page renders the list in a loop into the html table. The new employee record from the form is passed into the servlet where the persistence method
The Spring managed bean
is in the servlet retrieved manually. In the method
init() we first get the
and then a bean out of it. Notice that the bean ID is in fact a class name. This approach can help us to manage quite a lot of bean definitions in configuration files.
An important file for the web application is
web.xml. So have a look on some important parts
defines a path to the Spring context configuration. It’s the same file used also for JUnit tests.
is a listener initializing the Spring and its
The last file is
persistence.xml, in this case as very minimalistic. It defines a persistence unit including all entities (
@Entity) – in our case only Employee.
These are all parts of our application. To compile, test, build a WAR and deploy into Tomcat use the following command
If everything went well, then your application should be available at http://localhost:8080/spring-helloworld/employees
Application’s source code