Cookie Policy
We may store information about you using cookies (files which are sent by us to your computer or other access device) which
we can access when you visit our site in future. We do this to enhance user experience. If you want to delete any cookies that
are already on your computer, please refer to the instructions for your file management software to locate the file or directory
that stores cookies. Our cookies will have the file names symfony, JSESSIONID, IS and ISCOOKIE. Information on deleting or controlling
cookies is available at www.AboutCookies.org. Please note that by
deleting our cookies or disabling future cookies you may not be able to access certain areas or features of our site.

Spring 3 maven 2 web application step by step

Before writting this I admin that there are lots of tutorials like this but what I found is that they are not step by step guides, with missing vital parts of process of making it all happen from scratch. This makes you revert to the documentation and therefore defies the point of going through the tutorial. With this one I hope to make it a bit clearer, though I do not attempt to make it IDE specific, therefore there will be no guidance on how to do it in specific IDE. The layout will be to work with standard Maven project structure.

What is in this tutorial?

Maven Spring project configurations

Persistence using Hibernate and HSQLDB

Cache support using Ehcahe

Spring MVC configurations

Example integration tests for DB and Caching (Please not there are no Unit tests as I assume that the reader is familiar with those already)

Then the Spring context configuration (for webapp that is located in WEB-INF/spring/ directory as specified in web.xml parameters to the servlet):

classpath:spring-context.properties

The main context file contains two imports: spring/cache.xml that contains ehcache configuration and spring/persistence.xml that contains hibernate configuration

Note the p:shared="true" attribute. This ensures that we are using singleton manager for the Ehcache, which is important if you would like to use the same cache manager for your webapp and your hibernate 2nd level cache. "p:configLocation="classpath:ehcache.xml" tells Spring that we what to use the src/main/resources/ehcache.xml for our cache configurations

Persistence condifuration is quite simple. We setup dataSource first. Note that we use Spring variable substitution, which is defined by propertyConfigurer bean in context.xml that takes values from spring-context.properties. Then we define the hibernate factory and txProxyTemplate, which is used by transactional beans. It is good practice to manage transaction boundaries on the service layer. I.e. each method of service beans represents a unit of work and hence is a good candidate for a single transaction. For that purpose our Data access object is specifically not marked as transactional to prevent using it directly and hence have transaction per single db operation, which is not optimal. Instead we will make our service (WebCartServiceCached) transactional which will be using DAO and hence the transaction will be propagated to DAO.

hibernate/mapping.hbm.xml
NOTE: see org.springframework.transaction.TransactionDefinition
DAO: all beans must be wrapped into this proxy to allow seamless
transaction management integration via AOP.
PROPAGATION_REQUIRED,-Throwable

DAO object is very simple and uses Hibernates current session which is provided by txProxyTemplate from WebCartService to perform DB operations. Note that if we to use DAO bean directly we would have a Hibernate exception and no session is available standalone.

Our service uses DAO to provide business functions represented by WebCartServiceCached methods. For example #addToCart(final long pk, String item) will either find or create cart with specific primary key, add and item and persist the cart. All these db operations will happen in a single transaction. And if we have an exception all these changes are rolled back. So we have a good "all or nothing" strategy that will keep our db in a consistent state.

Caching is very simple. Facilitated by two annotations: @Cacheable(value = "cart") and @CacheEvict(value = "cart", allEntries = false, key = "#pk"). There are lots of configurations for this but this is the basic setup. @Cacheable tells ehcache to use cache named "cart" (this is why we have this entry in ehcache.xml) to keep results of this method. @CacheEvict allows to remove cache entries. In this case we remove a single entry by key 'pk', but it is possible to evict all items. As I already said it is very configurable.

Items:

${pageContext.request.contextPath} in jsp allows to reference the root of your webapp. This is very usefull if your webapp context name changes from environment to environment as this kind of url building approach will work everywhere consistently. Now if you navigate to localhost:8080/cart/1 you will see contents for cart with PK 1.

Here is screenshot of the outcome:

This sums up the basic Spring webapp project. Now we can have a look at how we can do integration tests for what we have written.

Firstly we need an alternative Spring context where we can remove all the MVC part so we can use it for core testing (i.e. services, dao). Note: that I am jumping to integration tests straight away since I assume that you know (and already done) unit tests. Integration tests is the final frontier! Before doing such tests appropriate unit test needs to be done! Please do not substitute these kind of tests for unit tests as they are considerably slower to run and much harder to test thoroughly.

The important elements are: include JUnit dependency in pom.xml, use @RunWith and @ContextConfiguration to tell JUnit what context configuration file you want to use. If you are testing DAO objects in isolation you can add @Transactional annotation to your Test suite at class level to provide the transaction support.

You also may have noticed that we use alternative context file /spring/testContext.xml. This context imports our original cache.xml and persistence.xml but provides override for spring-context.properties to supply alternative data source configurations and also does not contain the MVC configuration which are not needed for this test.