Monday, December 21, 2009

WebSphere JMS Sample Application

My previous blog I outlined the steps required to configure JMS resources for WebSphere Application Server 7.0. In that blog I promised to put together a sample application that can be installed to WebSphere Application Server and demonstrates three different implementations of sending JMS messages to a queue and retrieving the messages from a queue. The sample application is an Eclipse project interchange file. If you have Rational Application Developer installed on your computer you should be able to import this project into your workspace without too much hassle. Alternatively you can always use your favourite decompression tool to extract the contents to your local drive and then view the source from there.

Below are two diagrams describing the JMS runtime resources configured for the sample application:

Programmatic / Spring implementation



EJB3 implementation



Web client
To test the application I created a very simple web application that is used to trigger the sending of a JMS text message to a queue as well as to retrieve the message from the queue. I decided to use the Spring MVC  web framework to keep things simple. Below is a screen shot of the jms-tester web page:




Wednesday, December 9, 2009

WebSphere SIB, JMS queues and connection factory configuration

I was recently given a task to migrate an enterprise application that was running on SAP NetWeaver across to WebSphere application server. The application had a few session beans as well as a few message-driven beans. It used JMS to publish messages to a number of queues. This blog entry outlines the steps I took to configure the JMS queues and connection factories on WebSphere. It is pretty plain and boring but is really for my own benefit to be used as a reference and who knows maybe if you are reading this it may come in handy as well.

The following configurations were done on a single server of WebSphere application server 7.0. It assumes that the user is logged into the administration console and where global security has been enabled:

Create J2C authentication user
  • Security -> Global security -> Expand Java Authentication and Authorization Service -> J2C authentication data -> New
  • Enter in the following values:
    • Alias: myusr
    • User ID: myusr
    • Password: myusr
  • Click the OK button
  • Save to the master file configuration

Create group
  • Users and Groups -> Manage Groups -> Create
  • Enter in the following values:
    • Group name: mygrp
  • Click on the Group Membership button
  • Add the mygrp
  • Click the close button

Create user
  • Users and Groups -> Manage Users -> Create
  • Enter in the following values:
    • User ID: myusr
    • First name: Myusr
    • Last name: Mysurname
    • Password: mypassword
    • Confirm password: mypassword
  • Click on the Group Membership button
  • Click the Search button
  • Add the mygrp
  • Click the Close button
  • Click the Create button

Create SIB
  • Service integration -> Buses -> New
  • Bus Name: my_bus
  • Bus Security: enabled
  • Press next to enter the security wizard
  • Complete the wizard by accepting all the defaults
  • Save your changes by clicking the save link

Configure Authorization for the SIB
  • Service integration -> Buses
  • Select the Enabled link for the my_bus
  • [Authorization Policy] -> Users and groups in the bus connector role -> New
  • Enable Groups radio button and click the Next button
  • Select the mygrp checkbox and then the Next button
  • Click the OK button
  • Save to the master file configuration

Create Bus member for SIB
  • Service integration -> Buses -> my_bus -> [Topology] Destinations -> Bus members -> Add button
    • Enable the server radio button
  • Click the Next button
    • Enable the File store radio button
  • Finish the wizard by accepting all defaults
  • Save to the master file configuration

Create destinations for SIB
  • Service integration -> Buses -> my_bus -> [Destinations resources] Destinations -> New
  • Type: Queue
  • Next
  • Identifier: myFirstD
  • Select the bus member you created in the previous step
  • Finish the wizard by accepting all defaults
  • Save to the master file configuration

Configuring authorization on queue destinations
Optional because already has AllAuthenticated by default however it is recommended to remove this and add your own
  • Service integration -> Buses
  • Select the Enabled link for the my_bus
  • [Authorization Policy] -> Manage destination access roles
  • Select the myFirstD destination
  • Select the Add button
  • Enable Groups radio button and click the Next button
  • Select the mygrp checkbox and then the Next button
  • Check the Sender, Receiver and Browser checkboxes
  • Click the Finish button
  • Click the OK button
  • Save to the master file configuration

Create Connection Factory (Can also create Queue / Topic Connection Factory in a similar way)
  • Resources -> JMS -> Connection factories -> select server scope from the drop down list -> New
  • Default messaging provider -> Next
  • Enter in the following values:
    • Name: MyConnectionFactory
    • JNDI name: jms/MyConnectionFactory
    • Bus name: my_bus
    • Container-managed authentication alias: myusr
  • Click the OK button
  • Save to the master file configuration

Create JMS Queues (Can also create Topics in a similar way)
  • Resources -> JMS -> Queues -> select server scope from the drop down list -> New
  • Select the Default messaging provider radio button
  • Click the OK button
  • Enter in the following values:
    • Name: myFirstQ
    • JNDI name: jms/myFirstQ
    • Bus name: my_bus
    • Queue name: myFirstD
  • Select the OK button
  • Save to the master file configuration

Create Activation specifications
  • Resources -> JMS -> Activation specifications -> select server scope from the drop down list -> New
  • Select the Default messaging provider radio button
  • Click the OK button
  • Enter in the following values:
    • Name: myFirstSpec
    • JNDI name: eis/myFirstSpec
    • Destination type: Queue
    • Destination JNDI name: jms/myFirstQ
    • Bus name: my_bus
    • Authentication alias: myusr
  • Select the OK button
  • Save to the master file configuration

That's all there is to it. The next step will be configuring you application's resources and assigning them the correct authentication methods. I will describe those steps in my next blog along with a sample application.

Saturday, November 7, 2009

Scala – Transition from Java to Scala - My initial experience and thoughts

A couple of months ago I was given a task at work that required code to be written in Scala. At first I wasn't so thrilled about the fact that I would be learning a new language but I must say after spending some time with it I am glad I did. The hardest part in learning Scala was the "getting started" part. The syntax of the Scala code is very different from Java and it required me to "concentrate" and to think a little before I could start my very first "Hello World" application…as you can see I wasn't very motivated. The sample applications were also a little difficult to follow because I wasn’t familiar with the syntax it required a lot more thinking and a lot more concentration…sigh…yeah like I said in the beginning I wasn't very motivated. However having spent a couple of months programming in Scala I am a lot more familiar with the syntax and believe it or not  the code has become a lot more readable, a lot more flexible and more desirable to write than Java code. I am amazed at how much you can do with so little effort.

It doesn't take too much effort for somebody who is a Java programmer to learn Scala. Like I said in the beginning the hardest part for me was getting started but after that I became excited about what I could do with this language and I became motivated to learn more. Scala compiles to Java byte code and runs on the Java VM. You can reference existing Java libraries in your code and make full use of their classes. Scala pretty much does everything Java does but on top of that it offers a whole lot more. I am also enjoying learning other programming concepts and techniques. Scala is an object-oriented and functional programming language. I am learning a lot about functional programming and I have started thinking differently about how I can use these techniques and concepts to produce better code.

So if you are interested in learning Scala and come from a Java programming background like me than I would recommend the following links:

There are also a number of open source projects written in Scala and I would recommend anyone getting started to download the projects and take a look at the source code. Below are a few I have come across and learnt from:
  • Lift - Scala web framework
  • TalkingPuffin - Twitter client
  • Scalaffinity - library containing core functionality used by any social networking web site

Tuesday, September 1, 2009

SEAM - The Shopping Cart Web Application

Seam is ANOTHER web application framework. SIGH. Ok yes sigh another framework to learn but it is not entirely new, if you have been following along with the Shopping Cart tutorials where we used JSF, Facelets, Hibernate, JPA and RichFaces you will see that Seam is not something new just something extra.

This is not a tutorial in Seam more like a brief overview, introduction and comparison. Seam's documentation is pretty good to get started with. They also have sample applications so you can have a look to see how Seam is configured. I have also created a Seam web application based on the Shopping Cart application I did in previous posts. It is an Eclipse project. You will need to download the archived file and import it into your Eclipse workbench. I used JDK 1.6. The download is broken up into two parts simply because the file was too big to store on the server on its own:

  • ShoppingCartSeam.zip - This is the main archive that contains all 4 projects.
  • jboss-embedded-all.jar - A library used to run the embedded JBoss server when running our tests. Once you have imported the ShoppingCartSeam.zip archive into your Eclipse workbench please copy this file to the lib folder of the shopping-cart-test project.


Shopping Cart
I will highlight the major differences between the shopping cart application (that I will call Spring Application) we did in previous tutorials with this Seam shopping cart application.

1. Class diagrams
Below you will be able to compare the class diagram of the Spring application with the class diagram of the Seam application.

Spring class diagram


Seam class diagram


2. Spring vs EJB3
The design of our two applications stays pretty much the same, we still have our 3-tier architecture, i.e.
  • Presentation - GUI
  • Application - Business Logic
  • Data - Database

The difference being:
  • In the Spring application we have loosely coupled our application tier from our presentation tier by using Spring to manage and configure how we use and call our business layered objects. The view package contains all the logic for our GUI and is separated from our business logic. Also we use Spring to manage and configure our transactions.
  • In the Seam application we have tightly coupled our application tier to our presentation tier using Seam annotations and EJB3. There is some debate whether this is good or bad, at the end of the day they both have their advantages and disadvantages and it really depends on the type of project you are working on before deciding on which is better or worse. The Seam application uses an EJB3 session bean.

3. EAR vs WAR
The Spring application was packaged as a WAR as it didn’t have any EJB’s there was no need to create an EAR for it. There were two projects:
  • shopping-cart-web – web application
  • shopping-cart-core – project that contains all our business logic classes. It gets packaged as a JAR file and then added to our web application

Because it is packaged as a WAR we also didn’t need a full blown JEE server to deploy it to so Tomcat did the job quite nicely for us.

The Seam application is packaged as an EAR as it makes use of EJB3’s session beans. The project structure that was created for me when I used JBoss Tools to create a Seam project was the following:
  • shopping-cart – main web app
  • shopping-cart-ear – contains 3rd party libraries as well as datasource resource file used to connect to database
  • shopping-cart-ejb – EJB project that contains all our business logic classes (our entity beans and session beans)
  • shopping-cart-test – a standalone project that contains all our test classes

4. Entity classes
Both projects use the Java Persistence API (JPA) in the Entity classes (Basket, Item and BasketItem) to manage relational data and therefore the Entity classes are the same.

5. Faces Managed Beans
In our Spring application we are using the standard JSF library to manage our beans. We define our managed beans and set properties for it in the faces-config.xml file.

In the Seam application we define our managed beans in the beans class by using a Seam annotation (the annotation is called name and occurs just above the class declaration). Only navigational rules are defined in the faces-config file.

6. Web deployment descriptor
The Seam application has an additional filter and servlet defined in the web deployment descriptor, namely:

<filter>
 <filter-name>Seam Filter</filter-name>
 <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
</filter>
<filter-mapping>
 <filter-name>Seam Filter</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
 <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
</listener>
<servlet>
 <servlet-name>Seam Resource Servlet</servlet-name>
 <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
</servlet>
<servlet-mapping>
 <servlet-name>Faces Servlet</servlet-name>
 <url-pattern>*.seam</url-pattern>
</servlet-mapping>
<servlet-mapping>
 <servlet-name>Seam Resource Servlet</servlet-name>
 <url-pattern>/seam/resource/*</url-pattern>
</servlet-mapping>

7. JSPX vs XHTML
In the Spring application I created .jspx files for our web pages. I would have preferred to use .xhtml but Eclipse didn’t recognize code completion for me and showed that there were warnings when in actual fact there weren’t. I am sure there is some tweak out there to get rid of the warnings and to include code completion but I couldn’t find it and the hassle was not worth the time spent on it. So instead I used .jspx files which worked nicely for me.

In the Seam application I installed the JBoss Tools plugin for Eclipse and .xhtml files seemed to work fine without any errors.

8. Session vs Conversation
Seam introduces two new contexts, conversation and business process. In the Spring application I define the ShoppingViewHelper class with Session scope in the faces-config.xml file.

I could have done the same with the Seam application (by adding another Seam annotation to my class called Scope and given it a value of Session) instead I opted for the better more manageable context provided by Seam called Conversation context.

9. JUnit vs TestNG
In the Spring application we used the JUnit test framework for all our unit tests.

TestNG is another test framework that works the same as JUnit. TestNG is the default test framework chosen by Seam. You are not restricted to TestNG and can can still use JUnit if you like. You can create unit tests just like we did in the Spring application. Seam allows you to create integration tests quite easily to test a complete process from request to response without too much of an overhead. In order to do this Seam uses an embedded JBoss server. The embedded JBoss server is a lightweight server that only starts up the necessary services required to test your application.

Seam application:

The sample application was a really basic one, there is a lot more to Seam than what I touched on here.

Wednesday, August 5, 2009

Shopping Cart Web Application - Part 10 - AJAX

Introduction
Asynchronous JavaScript and XML (AJAX) is a group of interrelated web development techniques used for creating interactive web applications or rich Internet applications. With Ajax, web applications can retrieve data from the server asynchronously in the background without interfering with the display and behavior of the existing page. Data is retrieved using the XMLHttpRequest object or through the use of Remote Scripting in browsers that do not support it. Despite the name, the use of JavaScript and XML is not required, and they do not have to be used asynchronously

What you need before we get started

What we will cover
  • Advantages of AJAX
  • RichFaces
  • Limitations and rules
  • Shopping cart

Level
  • Beginner

Advantages of AJAX
  • Nice user experience - AJAX gives the user a way to interact with a website without having to wait for lengthy refreshes on a website. Sections of pages can be reloaded individually without having to reload the whole page
  • Less bandwidth used - instead of the full contents of the HTML page being sent to and from the server only the required information is transmitted. The network utilization is minimized and quicker operations occur
  • Limited processing on the server — Users may perceive the application to be faster or more responsive because only the necessary data is sent to the server, the server is not required to process all form elements. By sending only the necessary data, there is limited processing on the server. There is no need to process all form elements, process the viewstate, send images back to the client, and no need to send a full page back to the client

RichFaces 
RichFaces is an open source framework that adds Ajax capability into existing JSF applications without resorting to JavaScript. RichFaces leverages JavaServer Faces framework including lifecycle, validation, conversion facilities and management of static and dynamic resources. RichFaces UI library contains components for adding rich user interface features to JSF applications. Create a modern rich user interface look-and-feel with skins-based technology. RichFaces UI components come ready to use out-of-the-box, so developers save their time and immediately gain the advantage of the mentioned above features in Web applications creation. As a result, usage experience can be faster and easily obtained.

RichFaces allows to define (by means of JSF tags) different parts of a JSF page you wish to update with an Ajax request and provide a few options to send Ajax requests to the server. JSF page doesn't change from a "regular" JSF page and you don't need to write any JavaScript or XMLHTTPRequest objects by hands, everything is done automatically.

  • Ajax Filter - RichFaces uses a filter for a correction of code received on an Ajax request. In case of a "regular" JSF request a browser makes correction independently. In case of Ajax request in order to prevent layout destruction it's needed to use a filter, because a received code could differ from a code validated by a browser and a browser doesn't make any corrections
  • Ajax Action Components - There are Ajax Action Components: <a4j:commandButton>, <a4j:commandLink>, <a4j:poll>, <a4j:support>, etc. You can use them to send Ajax requests from the client side
  • Ajax Containers - AjaxContainer is an interface that describes an area on your JSF page that should be decoded during an Ajax request. AjaxViewRoot and AjaxRegion are implementations of this interface
  • JavaScript Engine - RichFaces JavaScript Engine runs on the client-side. It knows how to update different areas on your JSF page based on the information from the Ajax response. Do not use this JavaScript code directly, as it is available automatically

Limitations and Rules
  • Any Ajax framework should not append or delete, but only replace elements on the page. For successful updates, an element with the same ID as in the response must exist on the page. If you'd like to append any code to a page, put in a placeholder for it (any empty element). For the same reason, it's recommended to place messages in the "AjaxOutput" component (as no messages is also a message)
  • Don't use <f:verbatim> for self-rendered containers, since this component is transient and not saved in the tree
  • Ajax requests are made by XMLHTTPRequest functions in XML format, but this XML bypasses most validations and the corrections that might be made in a browser. Thus, create only a strict standards-compliant code for HTML and XHTML, without skipping any required elements or attributes. Any necessary XML corrections are automatically made by the XML filter on the server, but lot's of unexpected effects can be produced by an incorrect HTML code
  • The RichFaces ViewHandler puts itself in front of the Facelets ViewHandlers chain
  • RichFaces components uses their own renderers. On the Render Response Phase RichFaces framework makes a traversal of the component tree, calls its own renderer and puts the result into the Faces Response

Shopping Cart Application

1. RichFaces Filter
I added the RichFaces filter to the web deployment descriptor:

<filter>
 <display-name>RichFaces Filter</display-name>
 <filter-name>richfaces</filter-name>
 <filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
 <filter-name>richfaces</filter-name>
 <servlet-name>Faces Servlet</servlet-name>
 <dispatcher>REQUEST</dispatcher>
 <dispatcher>FORWARD</dispatcher>
 <dispatcher>INCLUDE</dispatcher>
</filter-mapping>

2. RichFaces components
I will only be adding AJAX components to the items.jspx page. The other pages can stay as they are as there isn’t a need to add any AJAX components to them. The first thing I did was add the RichFaces tag library xml namespaces to the items.jspx page. Below is the completed items.jspx page. I you compare it to the previous version you would realize that there is very little change, I just replaced most of the standard JSF components with RichFaces components.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" 
    xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core" 
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich"
    version="2.0">
<ui:composition template="/template.jspx">
 <ui:define name="body">
  <h:outputText id="headingOutTxt" value="#{msg.items_txt_heading}"
   styleClass="headingOutputText" />
  <a4j:form id="itemListFrm">
   <rich:dataTable id="itemsTbl" var="items" value="#{pc_Items.items}"
    binding="#{pc_Items.itemsTable}" styleClass="dataTable"
    columnClasses="dataTableCol1" rowClasses="dataTableRow1"
    headerClass="dataTableHeader">
    <rich:column id="nameCol">
     <f:facet name="header">
      <h:outputText id="nameHeaderOutTxt"
       value="#{msg.items_txt_name_col_header}" />
     </f:facet>
     <h:outputText id="nameOutTxt" value="#{items.name}" />
    </rich:column>
    <rich:column id="descriptionCol">
     <f:facet name="header">
      <h:outputText id="descriptionHeaderOutTxt"
       value="#{msg.items_txt_description_col_header}" />
     </f:facet>
     <h:outputText id="descriptionOutTxt" value="#{items.description}" />
    </rich:column>
    <rich:column id="priceCol">
     <f:facet name="header">
      <h:outputText id="priceHeaderOutTxt"
       value="#{msg.items_txt_price_col_header}" />
     </f:facet>
     <h:outputText id="priceOutTxt" value="#{items.price}">
      <f:convertNumber pattern="#{msg.currency_pattern}" />
     </h:outputText>
    </rich:column>
    <rich:column id="addActionCol">
     <a4j:commandLink id="buyLnk" value="#{msg.items_lnk_buy}"
      action="#{pc_Items.addItemToBasket}" reRender="basketTbl" />
    </rich:column>
   </rich:dataTable>
   <p />
   <h:outputText id="basketOutTxt" value="#{msg.items_txt_basket}" />
   <p />
   <rich:dataTable id="basketTbl" var="basketItem" styleClass="dataTable"
    columnClasses="dataTableCol1" rowClasses="dataTableRow1"
    value="#{shoppingViewHelper.basket.basketItems}"
    binding="#{pc_Items.basketTable}">
    <rich:column id="basketItemCol">
     <f:facet name="header">
      <h:outputText id="basketTblHeaderOutTxt"
       value="#{msg.items_txt_basket_item_col_header}" />
     </f:facet>
     <h:outputText id="basketItemOutTxt" value="#{basketItem.item.name}" />
    </rich:column>
    <rich:column id="basketItemQuantityCol">
     <f:facet name="header">
      <h:outputText id="basketTblQuantityOutTxt"
       value="#{msg.items_txt_basket_quantity_col_header}" />
     </f:facet>
     <h:outputText id="basketItemQuantityOutTxt" value="#{basketItem.quantity}" />
    </rich:column>
    <rich:column id="basketItemPriceCol">
     <f:facet name="header">
      <h:outputText id="basketTblPriceOutTxt"
       value="#{msg.items_txt_basket_price_col_header}" />
     </f:facet>
     <h:outputText id="basketItemPriceOutTxt" value="#{basketItem.price}" />
    </rich:column>
    <rich:column id="removeActionCol">
     <a4j:commandLink id="removeLnk" value="#{msg.items_lnk_remove}"
      action="#{pc_Items.removeItemFromBasket}" reRender="basketTbl" />
   </rich:column>
   </rich:dataTable>
   <p />
   <h:commandButton id="checkoutBtn" value="#{msg.btn_checkout}"
    action="#{pc_Items.checkout}" />
   <rich:messages errorClass="errorText" /> 
  </a4j:form>
 </ui:define>
</ui:composition>
</jsp:root>

3. Items backing bean
There are two very small changes we need to make to the Items backing bean (Items.java). Our itemsTbl datatable and our basketTbl datatable are bound to javax.faces.component.html.HtmlDataTable objects within our Items.java backing bean. Because our datatables are no longer standard JSF datatables but RichFaces datatables we need to change this binding from a javax.faces.component.html.HtmlDataTable to a org.richfaces.component.UIDataTable.

The end result:



As you can see it was actually pretty simple to get up and running. Please visit the RichFaces demo site to see the full range of RichFaces components in action. You may have to register on their website to view the demo but it is well worth it. Also please read through the RichFaces developers guide . It is very useful reference manual that contains a comprehensive guide to all of the RichFaces components.

Tuesday, August 4, 2009

Shopping Cart Web Application - Part 9 - Advanced Test Cases

Introduction
Our application has grown in size and complexity since the last time we created our unit test for the shopping service class. This is what I would like to do:
  • Integrate our test case with Spring – this is pretty cool, instead of creating and initializing our objects manually or performing any JNDI looking ups ourselves (that is if we did need to do that) we will let Spring take care of this for us using our existing Spring bean configuration files we created in the previous tutorial.
  • Mock objects – In some cases it is very difficult to test a service. In our case it isn’t because all we are doing is creating an instance of the service ourselves but what if the instance of the service existed on a remote server and you needed to use a remote call to lookup that instance? It adds additional overhead to your test case. For one it relies on this remote service to be available at the time the test is run and two it requires additional resources in order to perform this lookup. An alternative to testing the service is to create a mock of the service and predict the outcome of the test. So you don’t actually test the service implementation but your very own mock that is based on the service interface. This sounds like a lot of work but it isn’t actually thanks to a third party library we are going to use called EasyMock.
  • Database integration testing – We touch on an integration test for testing transactions with the database. We will be using spring as well as a third party library called DBUnit.

What you need before we get started
  • ShoppingCartAdvancedTestCasesPart9 sample application. - This is an Eclipse archive file that contains one Eclipse project. Please import this project into your Eclipse environment.
  • You will need the previous third party libraries that were mentioned and used in earlier parts to this tutorial
  • The following libraries need to be added to your existing Libs project:

What we will cover
  • Spring integration
  • Mock object tests
  • Database integration tests

Level
  • Intermediary

Spring Integration
We are going to use Spring for two purposes, the first is for our Shopping service class. We will let Spring manage the creation and initialization of this object for us so. We will also make use of our existing spring bean configuration file to initialize our service class. Secondly we are going to use Spring to create test data for us so that we can use it in our test case. To do this we will create a Spring bean configuration file specifically for our tests. I have put it under our test folder and called it shoppingcart-test.xml.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
  <bean id="shoppingService" class="com.mydomain.shoppingcart.service.impl.ShoppingManager">
    <property name="itemDao">
      <ref bean="itemDao" />
    </property>
    <property name="basketDao">
      <ref bean="basketDao" />
    </property>
  </bean>
  <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="shoppingCartDataSource" />
  </bean>
  <import resource="classpath:shoppingcart-database.xml" />
</beans>


There are two different beans defined here, namely:
  • shoppingService – our shopping service class
  • jdbcTemplate – spring class used to simplify the use of JDBC

Next we will make changes to our ShoppingServiceTest class.

package com.mydomain.shoppingcart.service.test;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.util.LinkedList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.mydomain.shoppingcart.bo.Basket;
import com.mydomain.shoppingcart.bo.BasketItem;
import com.mydomain.shoppingcart.bo.Item;
import com.mydomain.shoppingcart.dao.BasketDao;
import com.mydomain.shoppingcart.service.ShoppingService;

/**
* @author Ross
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/shoppingcart-test.xml" })
public class ShoppingServiceTest {
  private Basket basket;
  private BasketDao basketDaoMock;
  @Autowired
  private ShoppingService shoppingManager;
  private ShoppingService shoppingManagerMock;
  private Item testItem;

 /**
  * Tests adding an item to the basket.
  */
  @Test
  @DirtiesContext
  public void addItem() {
    int itemCount = basket.getItemCount();
    basket.addItem(testItem);
    assertEquals(itemCount + 1, basket.getItemCount());
  }

 /**
  * Tests emptying the basket.
  */
  @Test
  @DirtiesContext
  public void empty() {
    basket.empty();
    assertEquals(0, basket.getItemCount());
  }

 /**
  * Tests finding items.
  */
  @Test
  public void findItems() {
    try {
      int itemCount = basket.getItemCount();
      List<Item> mockResult = new LinkedList<Item>();
      for (int i = 0; i < itemCount; i++) {
        mockResult.add(new Item());
      }
      expect(shoppingManagerMock.findItems()).andReturn(mockResult);
      replay(shoppingManagerMock);

      List<Item> allItems = new LinkedList<Item>(shoppingManagerMock.findItems());
      assertEquals(itemCount, allItems.size());

      verify(shoppingManagerMock);
    } catch (Exception e) {
      e.printStackTrace();
      fail("Error in Shopping Manager");
    }
  }

 /**
  * Tests removing an item from the cart.
  */
  @Test
  @DirtiesContext
  public void removeItem() {
    int itemCount = basket.getItemCount();
    for (BasketItem basketItem : basket.getBasketItems()) {
      basket.removeItem(basketItem.getItem());
      break;
    }
    assertEquals(itemCount - 1, basket.getItemCount());
  }

 /**
  * Tests saving a basket.
  */
  @Test
  public void saveBasket() {
    try {
      shoppingManager.setBasketDao(basketDaoMock);
      basketDaoMock.saveOrUpdateBasket(basket);
      replay(basketDaoMock);
      shoppingManager.updateBasket(basket);
      verify(basketDaoMock);
    } catch (Exception e) {
      e.printStackTrace();
      fail("Error in Shopping Manager");
    }
  }

 /**
  * Sets up the test fixture.
  *
  * Called before every test case method.
  */
  @Before
  public void setUp() {
    try {
      shoppingManagerMock = createMock(ShoppingService.class);
      basketDaoMock = createMock(BasketDao.class);
      testItem = new Item(1l, "Candy Cotton", "Candy coated milky tarts", 8.50d);
      basket = new Basket();
      basket.addItem(new Item(2l, "Jelly Beans", "Jelly icecream waffle cream", 18.99d));
      basket.addItem(new Item(3l, "Jam Doughnut", "Strawberry jam and Christmas pudding", 23.00d));
    } catch (Exception e) {
      e.printStackTrace();
      fail("Error setting up test case");
    }
  }
}

Ok there are a couple of things I would like to point out here and step through them each:
  • @RunWith attribute is a JUnit annotation and is used when you want to override the default JUnit runner. Here we want to use Springs own implementation in order to use Spring in our tests.
  • @ContextConfiguration is a Spring annotation and sets the location of the Spring bean configuration files needed for this test.
  • @Autowired is a Spring annotation that tells the compiler to automatically "wire" the variable (in this case shoppingManager) to the matching bean configured in the Spring bean configuration file.
  • Lastly we have our test method. Nothing really fancy about the body of the method. You notice we didn't have to create any objects or initialize anything as Spring did that for us. There is one more additional Spring annotation, @DirtiesContext. This annotation ensures that this method gets a clean context before it executes. Another test method may have altered the state of the beans defined in the Spring configuration files this annotation ensures the state of those beans will be the same as its original state before it executes.

Mock object test
Mock objects are simulated objects that mimic the behavior of real objects in controlled ways. A mock object is created to test the behavior of some other object. Mock objects can simulate the behavior of complex, real (non-mock) objects and are therefore useful when a real object is impractical or impossible to incorporate into a unit test. If an object has any of the following characteristics, it may be useful to use a mock object in its place:
  • Supplies non-deterministic results (e.g. the current time or the current temperature)
  • Has states that are difficult to create or reproduce (e.g. a network error)
  • Is slow (e.g. a complete database, which would have to be initialized before the test)
  • Does not yet exist or may change behavior
  • Would have to include information and methods exclusively for testing purposes (and not for its actual task)
  • Mock objects have the same interface as the real objects they mimic, allowing a client object to remain unaware of whether it is using a real object or a mock object.

EasyMock
EasyMock is a third party library that provides Mock Objects for interfaces in JUnit tests by generating them on the fly.

Shopping Cart Application
In the shopping cart application I created two different mock objects to show you how and where you can use them:
  • ShoppingManagerMock – A mock for the shopping service interface. You would most likely want to create a mock object for a service that you are looking up remotely and have no control over it. In the shopping cart application this is not the case but this example demonstrates what you can do.
  • BasketDaoMock – A mock for the basket dao. You may not want to test your service class but not the actual persistence of data to the database. Simply because there is a performance overhead setting up connections and persisting data to the database as well as managing the test data that you save and delete from the database. You don't want to corrupt your database with your tests. The last part of this tutorial shows you an example of testing your DAO's.

In our setup method we create the mock objects using EasyMocks createMock static method. This call creates a mock object that implements the given interface.

The first thing we do is define what method calls we expect should be made on our mock object. We can also define what result we expect back from a method call:

expect(shoppingManagerMock.findItems()).andReturn(mockResult); 

Once we have set up all our expectations (in our case only one) we change the mode of our mock test to replay. What this means is that every other method call made on our mock object from this point on will be checked to see if it is what we expect to be called.

replay(shoppingManagerMock); List<Item> allItems = new LinkedList<Item>(shoppingManagerMock.findItems()); assertEquals(itemCount, allItems.size());

Finally at the end of our test we call the EasyMock verify method that verifies the expected behaviour and throws an exception if it does not match.

verify(shoppingManagerMock); 

I created a new test method to test the BasketDao mock object. As you can see it is very similar to the above test. You will notice that I am not using the shopping manager mock object.

@Test
public void saveBasket() {
  try {
    shoppingManager.setBasketDao(basketDaoMock);
    basketDaoMock.saveOrUpdateBasket(basket);
    replay(basketDaoMock);
    shoppingManager.updateBasket(basket);
    verify(basketDaoMock);
  } catch (Exception e) {
    e.printStackTrace();
    fail("Error in Shopping Manager");
  }
}

Database Integration Tests
I would call this a type of integration test because we are testing the integration of our application with the database. I created a new test called BasketDaoTest to test the BasketDao data access class. These are the following steps I took when putting together this test:
  • Create test data that we will use to insert into our database and then remove at the end of the test
  • Create new test class to test the BasketDao class

1. Test data
We are going to create test data to run our tests against. You don’t want to run your test against data already in the database. For one you don’t know what data is there and two you don’t want to mess with someone else’s data. It is therefore essential to create our own data.
I created an xml file (shoppingcart-dbunit.xml) for my test data that will be used by DBUnit to insert into the database and at the end of the test remove it from the database. An example of the xml I used looks like the following:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
  <basket ID="100001" />
  <item ID="100001" DESCRIPTION="Candy coated milky tarts" NAME="Candy Cotton" PRICE="8.5"/>
  <item ID="100002" DESCRIPTION="Jelly icecream waffle cream" NAME="Jelly Beans" PRICE="18.99"/>
  <basket_item ID="100001" BASKET_ID="100001" ITEMS_ID="100001" QUANTITY="2" PRICE="17"/>
  <basket_item ID="100002" BASKET_ID="100001" ITEMS_ID="100002" QUANTITY="1" PRICE="18.99"/>
</dataset>

DbUnit is a JUnit extension targeted at database-driven projects that puts your database into a known state between test runs. The easiest way to create this test data is to export the data from the database. There are specific DBUnit classes you can use to export data in the format required either by writing a java application that does it or by using an ant task made available by DBUnit to do this.


2. Test class
Now that we the data that our test is going to use we can move right along to our test class.
Once again we will leverage off Spring to make our lives a whole lot easier. If you take a look at our class declaration you will notice a couple of interesting points.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/shoppingcart-test.xml" })
@TransactionConfiguration
@Transactional
public class BasketDaoTest extends AbstractTransactionalJUnit4SpringContextTests {

This class is an abstract transactional extension of AbstractJUnit4SpringContextTests () which adds convenience functionality for JDBC access. It expects a DataSource bean and a PlatformTransactionManager bean to be defined in the Spring application context.

This class exposes a SimpleJdbcTemplate and provides an easy way to count the number of rows in a table, delete from the database , and execute SQL scripts within a transaction.

The @TransactionConfiguration and @Transactional annotations configure transactions for the tests.

I have broken our test class up into the following steps:
  1. Record current state of data in the database
  2. Insert test data into the database
  3. Run test on data in database
  4. Delete test data from database
  5. Validate data stored in the database to match original state

1. Record current state of data in the database
The first step I decided to do is to determine how many rows there are for the basket table. I did this so that at the end of the test I can compare the number of rows in the basket table to this value and check to see whether or not they are equal.

@BeforeTransaction
public void beforeTransaction() {
  basketTableRowCount = countRowsInTable(BASKET_TABLE_NAME);
}

The method with the annotation @BeforeTransaction is run before the transaction starts.

2. Insert test data into the database
I take the test data we created and I use DBUnit classes to insert the data into the database.

@Before
public void setUpTestDataWithinTransaction() {
  try {
    IDatabaseConnection connection = new DatabaseConnection(jdbcTemplate.getDataSource().getConnection());
    DatabaseOperation.INSERT.execute(connection, new FlatXmlDataSet(new FileInputStream(TEST_DATA_FILE)));
    jdbcTemplate.getDataSource().getConnection().close();
  } catch (Exception e) {
    e.printStackTrace();
  }
}

As we saw in the earlier tutorial on test cases the method with a @Before annotation gets called before any test methods.

3. Run test on data in database
All our JUnit test methods can now be run

@Test
@Rollback(true)
public void saveOrUpdateBasket() {
  assertNotNull("Basket DAO is null.", basketDao);
  try {
    Collection<Basket> baskets = basketDao.loadById(1);

    assertNotNull("Basket list is null.", baskets);
    assertEquals("Number of baskets should be " + basketTableRowCount + 1 + ".", basketTableRowCount + 1, baskets.size());

    for (Basket basket : baskets) {
      assertNotNull("Basket is null.", basket);
    }
  } catch (Exception e) {
    fail("Error in saveOrUpdateBasket");
  }
}

The @Test annotation identifies this method as our test method to run. The @Rollback annotation is a Spring test annotation used to indicate whether or not the transaction for the annotated test method should be rolled back after the test method has completed. If true, the transaction will be rolled back; otherwise, the transaction will be committed.

4. Delete test data from database
At the end of all our tests we use DBUnit again to delete our test data from the database so that the state of the database returns to what it was before the start of our test case.

@After
public void tearDownWithinTransaction() {
  try {
    IDatabaseConnection connection = new DatabaseConnection(jdbcTemplate.getDataSource().getConnection());
    DatabaseOperation.DELETE.execute(connection, new FlatXmlDataSet(new FileInputStream(TEST_DATA_FILE)));
    jdbcTemplate.getDataSource().getConnection().close();
  } catch (Exception e) {
    fail("Error in tearDownWithinTransaction");
  }
}

As we saw in the earlier tutorial on test cases the method with a @After annotation gets called after all the test methods have been called.

5. Validate data stored in the database to match original state
Here we validate the number of rows in our basket table to the number we originally retrieved at the start of our test.

@AfterTransaction
public void afterTransaction() {
  assertEquals(basketTableRowCount, countRowsInTable(BASKET_TABLE_NAME));
}

The method with the annotation @AfterTransaction is run after the transaction ends.

Wednesday, July 15, 2009

Shopping Cart Web Application - Part 8 - Spring

Introduction
The Spring Framework provides solutions to many technical challenges faced by Java developers and organizations wanting to create applications based on the Java platform. Because of the size and complexity of the functionality offered, it can be hard to distinguish the major building blocks from which the framework is composed.

The Spring Framework can be considered as a collection of smaller frameworks. Most of these frameworks are designed to work independently of each other yet provide better functionalities when used together. These frameworks are divided along the building blocks of typical complex applications:

  • Inversion of Control container - configuration of application components and lifecycle management of Java objects.
  • Aspect-oriented programming framework - working with functionalities which cannot be implemented with Java's object-oriented programming capabilities without making sacrifices.
  • Data access framework - working with relational database management systems on the Java platform using JDBC and Object-relational mapping tools providing solutions to technical challenges which are reusable in a multitude of Java-based environments.
  • Transaction management framework - harmonization of various transaction management API's and configurative transaction management orchestration for Java objects.
  • Model-view-controller framework - HTTP and Servlet based framework providing many hooks for extension and customization.
  • Remote Access framework - configurative RPC-style export and import of Java objects over computer networks supporting RMI, CORBA and HTTP-based protocols including web services (SOAP).
  • Authentication and authorization framework - configurative orchestration of authentication and authorization processes supporting many popular and industry-standard standards, protocols, tools and practices via the Spring Security sub-project (formerly Acegi).
  • Remote Management framework - configurative exposure and management of Java objects for local or remote configuration via JMX.
  • Messaging framework - configurative registration of message listener objects for transparent message consumption from message queues via JMS, improvement of message sending over standard JMS API's.
  • Testing framework - support classes for writing unit tests and integration tests.

What you need before we get started

What we will cover
  • Spring and Hibernate
  • Shopping Cart application Spring configuration file
  • Shopping Cart application Data Access Objects
  • Shopping Cart application Web Spring bean configuration file

Level
  • Beginner

The Spring Framework covers a lot of ground and we are only going to scratch the surface. We will add Spring to our Shopping Cart Application and I will show how Spring can be used to make our lives a lot easier. The main goal for this tutorial is to show you how to integrate Spring with Hibernate.

Spring and Hibernate
As learnt in the previous Hibernate tutorial Hibernate is a powerful ORM tool that lies between the Application and the Database. It enables applications to access data from any database in a platform-independent manner. There is no need for the application to depend on the low-level JDBC details like managing connection, dealing with statements and result sets. All the necessary details for accessing a particular data source is easily configurable in xml files.

One of the problems with using Hibernate is that the client application that accesses the database using Hibernate framework has to depend on the Hibernate APIs like Configuration, SessionFactory and Session. These objects will continue to get scattered across the code throughout the application. Moreover, the application code has to manually maintain and manage these objects. In the case of Spring, the business objects can be highly configurable with the help of IOC Container. It is possible to use the Hibernate objects as Spring Beans and they can enjoy all the facilities that Spring provides.

Shopping Cart application Spring configuration file
In Spring, all the business objects are configured in xml files and the configured business objects are called Spring Beans. These Spring Beans are maintained by the IOC which is given to the client application upon request.

1. Hibernate Session Example
In the Hibernate tutorial we created a hibernate.cfg.xml file. In this tutorial we are going to replace this file with a Spring bean configuration file. The Hibernate configuration will be configured in the Spring configuration class as opposed to the hibernate configuration file. The details of the Spring bean configuration file are pasted below:

shoppingcart-database.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
  <bean id="shoppingCartDataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
    <property name="url" value="jdbc:hsqldb:shoppingcart" />
    <property name="username" value="sa" />
    <property name="password" value="" />
  </bean>
  <bean id="shoppingCartSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="shoppingCartDataSource" />
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
        <prop key="show_sql">true</prop>
        <prop key="format_sql">true</prop>
        <prop key="current_session_context_class">thread</prop>
      </props>
    </property>
    <property name="annotatedClasses">
      <list>
        <value>com.mydomain.shoppingcart.bo.Item</value>
        <value>com.mydomain.shoppingcart.bo.Basket</value>
        <value>com.mydomain.shoppingcart.bo.BasketItem</value>
      </list>
    </property>
  </bean>
  <bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
      <ref local="shoppingCartSessionFactory" />
    </property>
  </bean>
  <bean id="basketDao" class="com.mydomain.shoppingcart.dao.impl.BasketDaoImpl">
    <property name="sessionFactory">
      <ref local="shoppingCartSessionFactory" />
    </property>
  </bean>
  <bean id="itemDao" class="com.mydomain.shoppingcart.dao.impl.ItemDaoImpl">
    <property name="sessionFactory">
      <ref local="shoppingCartSessionFactory" />
    </property>
  </bean>
</beans>

1.1. shoppingCartDataSource
The shoppingCartDataSource bean defines a data-source of type 'org.apache.commons.dbcp.BasicDataSource'. More importantly, it defines the various connection properties that are needed for accessing the database. Since we are using HSQL as our database I have specified the hsqldb driver.

1.2. shoppingCartSessionFactory
The shoppingCartSessionFactory bean is responsible for creating Session objects through which Transaction and Data accessing is done. It replaces the session factory configuration we made in the Hibernate tutorial’s hibernate.cfg.xml file. We can also delete the HibernateUtil class we created in the Hibernate tutorial to get a handle on the session factory as Spring is going to do all of that for us.

1.3. transactionManager
The transactionManager bean binds a Hibernate Session from the factory to a thread to support transactions.

1.4. basketDao and itemDao
These last two beans are references to our very own data access objects. I have defined them here to tell Spring to manage the creation of these objects for me and to initialise them with the sessionFactory class.

2. JPA EntityManager Example
In the Hibernate tutorial for the JPA example we created a persistence.xml file. This file stays exactly the same. In this tutorial we are going to add a Spring bean configuration file and tell it that we are using JPA Entity Manager. The details of the Spring bean configuration file are pasted below:

shoppingcart-database.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
      http://www.springframework.org/schema/tx 
      http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
 
 <bean id="entityManagerFactory"
  class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
  <property name="persistenceUnitName" value="shopping-cart" />
 </bean>
 
 <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
  <property name="entityManagerFactory">
   <ref local="entityManagerFactory" />
  </property>
 </bean>
 <bean
  class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
 
 <bean id="basketDao" class="com.mydomain.shoppingcart.dao.impl.BasketDaoImpl">
  <property name="entityManagerFactory" ref="entityManagerFactory" />
 </bean>
 
 <bean id="itemDao" class="com.mydomain.shoppingcart.dao.impl.ItemDaoImpl">
  <property name="entityManagerFactory" ref="entityManagerFactory" />
 </bean>
 
 <tx:annotation-driven />
</beans>

2.1. entityManagerFactory
The entityManagerFactory is a FactoryBean that creates a JPA EntityManagerFactory according to JPA's standard standalone bootstrap contract.

2.2. transactionManager
The transactionManager bean is a PlatformTransactionManager implementation for a single JPA EntityManagerFactory used to support transactions.


2.3. basketDao and itemDao
Like in the Hibernate example I have defined the DAO classes. They both extend the Spring JJpaDaoSupport helper class.

Shopping Cart application Data Access Objects

1. Hibernate Session Example
As you know we have two DAO implementations, BasketDaoImpl and ItemDaoImpl. We configured these classes already in our Spring bean configuration file so we know that Spring is going to manage the creation and initialisation of these classes for us. I have also made sure these classes both extend Springs HibernateDaoSupport class. The HibernateDaoSupport class is a convenient super class for Hibernate-based data access objects. It requires a SessionFactory to be set, providing a HibernateTemplate based on it to subclasses through the getHibernateTemplate() method.

BasketDaoImpl.java
@Transactional
public class BasketDaoImpl extends HibernateDaoSupport implements BasketDao {

    public void delete(final Basket basket) throws Exception {
        HibernateCallback callback = new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Object basketObj = session.load(Basket.class, basket.getId());
                session.delete(basketObj);
                return null;
            }
        };
        getHibernateTemplate().execute(callback);
    }

    public void saveOrUpdateBasket(final Basket basket) throws Exception {
        HibernateCallback callback = new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                session.saveOrUpdate(basket);
                return null;
            }
        };
        getHibernateTemplate().execute(callback);
    }

    public Basket removeItemFromBasket(final BasketItem basketItem) throws Exception {
        HibernateCallback callback = new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {

                Basket basket = (Basket) session.load(Basket.class, basketItem.getBasket().getId());
                for (Iterator<BasketItem> it = basket.getBasketItems().iterator(); it.hasNext();) {
                    BasketItem existingBasketItem = (BasketItem) it.next();
                    if (existingBasketItem.getId().equals(basketItem.getId())) {
                        if (existingBasketItem.getQuantity() > 1) {
                            existingBasketItem.decreaseQuantity();
                        } else {
                            it.remove();
                        }
                    }
                }
                session.saveOrUpdate(basket);
                return basket;
            }
        };
        return (Basket) getHibernateTemplate().execute(callback);
    }
}

I will step through the saveOrUpdateBasket method only as the others are very similar. The first thing you will notice is the instantiation of an anonymous class from a Spring interface called HibernateCallback.

There is one method inside this class called doInHibernate. This method will be called by the HibernateTemplate’s execute method. An active Hibernate session is passed to this method. As you can see we don’t care about activating or closing the Session, or handling transactions. This is all taken care of by Spring.

2. JPA Entity Manager Example
The BasketDaoImpl class in the JPA sample application extends Springs helper class (JpaDaoSupport):

BasketDaoImpl.java
@Transactional
public class BasketDaoImpl extends JpaDaoSupport implements BasketDao {

    public void delete(Basket basket) throws Exception {
        basket = getJpaTemplate().find(Basket.class, basket.getId());
        getJpaTemplate().remove(basket);
    }

    public Basket update(Basket basket) throws Exception {
        return getJpaTemplate().merge(basket);
    }
    
    public Basket removeItemFromBasket(BasketItem basketItem) throws Exception {
        Basket basket = getJpaTemplate().find(Basket.class, basketItem.getBasket().getId());
        for (Iterator<BasketItem> it = basket.getBasketItems().iterator(); it.hasNext(); ) {
            BasketItem existingBasketItem = (BasketItem) it.next();
            if (existingBasketItem.getId().equals(basketItem.getId())) {
                if (existingBasketItem.getQuantity() > 1) {
                    existingBasketItem.decreaseQuantity();
                } else {
                    it.remove();
                }
            }
        };
        return getJpaTemplate().merge(basket);
    }
}

Shopping Cart application Web Spring bean configuration file
I created a Spring bean configuration file for the web project as well. The main reason for this was so that I would let Spring manage the creation and retrieval of our ShoppingManager service. I created a file called applicationContext.xml and saved it in the WebContent/WEB-INF directory.

applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
 <bean id="shoppingService" class="com.mydomain.shoppingcart.service.impl.ShoppingManager">
  <property name="itemDao">
   <ref bean="itemDao" />
  </property>
  <property name="basketDao">
   <ref bean="basketDao" />
  </property>
 </bean>
 <import resource="classpath:shoppingcart-database.xml" />
</beans>

Sunday, July 5, 2009

Shopping Cart Web Application - Part 7 - Hibernate


Introduction
Hibernate is an object-relational mapping (ORM) library for the Java language, providing a framework for mapping an object-oriented domain model to a traditional relational database.
If you are new to Hibernate I would suggest reading the documentation on the Hibernate website as well as this tutorial.

What you need before we get started


What we will cover

  • Hibernate Overview
  • Java Persistence API
  • Shopping cart web application changes


Level
  • Beginner

Overview
Hibernate's primary feature is mapping from Java classes to database tables (and from Java data types to SQL data types). Hibernate also provides data query and retrieval facilities. Hibernate generates the SQL calls and relieves the developer from manual result set handling and object conversion, keeping the application portable to all supported SQL databases, with database portability delivered at very little performance overhead.

Java Persistence API
The Java Persistence API (JPA) provides an object/relational mapping facility to Java developers for managing relational data in Java applications. Java Persistence consists of three areas:
  • The Java Persistence API
  • The query language
  • Object/relational mapping metadata

JPA was introduced in JEE 5 and forms part of the JSR 220 EJB3.0 specification. The Java Persistence API draws upon the best ideas from persistence technologies such as Hibernate, TopLink, and JDO. Customers now no longer face the choice between incompatible non-standard persistence models for object/relational mapping.

Both sample applications use JPA annotations in the Entity classes, the difference between the two is in the data access objects. The Hibernate sample application makes use of Hibernate's session factory to read and write to the database whereas the JPA sample application makes use of JPA's EntityManager to read and write to the database.  

For further reading and information on JPA I recommend these links:

Shopping Cart Web Application


Database Schema
Below is a schema of the database I want my application to use:



The SQL statements for the creation of these tables for this database will look like:
create table basket (id bigint not null unique, primary key (id)) ENGINE=InnoDB;
create table basket_item (id bigint not null unique, price double precision not null, quantity integer not null, items_id bigint not null, basket_id bigint not null, primary key (id)) ENGINE=InnoDB;
create table item (id bigint not null unique, description varchar(255), name varchar(255) not null, price double precision not null, primary key (id)) ENGINE=InnoDB;
alter table basket_item add index FK3F6FA5ECF59CCC6 (basket_id), add constraint FK3F6FA5ECF59CCC6 foreign key (basket_id) references basket (id);
alter table basket_item add index FK3F6FA5EC98F3A8D9 (items_id), add constraint FK3F6FA5EC98F3A8D9 foreign key (items_id) references item (id);

The above basket table is pretty useless but I wanted an example which had a many-to-one association with items. The basket table could also include more columns such as username.

HSQLDB
HSQLDB (Hyperthreaded Structured Query Language Database) is a relational database management system written in Java. The reason I have chosen this database over MySQL or any other database is because I wanted an in-memory database so that it would be easier for readers who are unfamiliar with configuring databases to get my sample application up and running without much hassle. Using HSQLDB’s in-memory database all I had to do was include the HSQLDB library in my applications classpath. Hibernate will create the database for me and prepopulate our database with necessary data.

Hibernate configuration file vs Persistence configuration file
The Hibernate sample application requires a Hibernate configuration file whereas the JPA sample application requires a persistence configuration file. Both are very similar:

1. Hibernate configuration file
Hibernate uses a file (hibernate.cfg.xml) to configure hibernate properties such as connection details to the database, location of the entity classes used to create tables in the database and a whole range of other settings. This is a copy of the hibernate.cfg.xml we used in the Shopping Cart application:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
  "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
        <property name="hibernate.connection.url">jdbc:hsqldb:shoppingcart</property>
        <property name="hibernate.connection.username">sa</property>
        <property name="connection.password"></property>
        <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="hbm2ddl.auto">create</property>
        <property name="current_session_context_class">thread</property>
        
        <mapping class="com.mydomain.shoppingcart.bo.Item" />
        <mapping class="com.mydomain.shoppingcart.bo.Basket" />
        <mapping class="com.mydomain.shoppingcart.bo.BasketItem" />
    </session-factory>
</hibernate-configuration>

2. Persistence configuration file
Much like the Hibernate configuration file the persistence configuration file is used to configure the JPA context.
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
    http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
 version="1.0">
 <persistence-unit name="shopping-cart" transaction-type="RESOURCE_LOCAL">
  <properties>
   <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />
   <property name="hibernate.connection.url" value="jdbc:hsqldb:shoppingcart" />
   <property name="hibernate.connection.username" value="sa" />
   <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
   <property name="hibernate.archive.autodetection" value="class" />
   <property name="hibernate.show_sql" value="true" />
   <property name="hibernate.format_sql" value="true" />
  </properties>
 </persistence-unit>
</persistence>


Annotations
Many APIs require a fair amount of boilerplate code (any code that is or can be reused in new contexts or applications without being changed much from the original). For example, in order to write a JAX-RPC web service, you must provide a paired interface and implementation. This boilerplate could be generated automatically by a tool if the program were “decorated” with annotations indicating which methods were remotely accessible.

Annotations are like meta-tags that you can add to your code and apply them to package declarations, type declarations, constructors, methods, fields, parameters, and variables. As a result, you will have helpful ways to indicate whether your methods are dependent on other methods, whether they are incomplete, whether your classes have references to other classes, and so on.

Annotation-based development relieves Java developers from the pain of cumbersome configuration. Annotation-based development lets us avoid writing boilerplate code under many circumstances by enabling tools to generate it from annotations in the source code. This leads to a declarative programming style where the programmer says what should be done and tools emit the code to do it.

Mapping with EJB3/JPA Annotations
Every bound persistent POJO class is an entity bean and is declared using the @Entity annotation (at the class level). Below is an extract of the code of what our Item class now looks like having annotations added to it:

Item.java
@Entity
@Table(name="item")
public class Item implements Serializable  {
 private static final long serialVersionUID = 1135428828106917172L;
 private String description;
 private Long id;
 private String name;
 private Double price;
 private List<BasketItem> basketItems = new ArrayList<BasketItem>(0);
 
 public Item() {
 }

 public Item(Long id, String name, double price) {
  this.id = id;
  this.name = name;
  this.price = price;
 }

 public Item(Long id, String description, String name, double price) {
  this.id = id;
  this.description = description;
  this.name = name;
  this.price = price;
 }
 
 @Column(name="description")
 public String getDescription() {
  return description;
 }

 @Id
 @GeneratedValue(strategy=GenerationType.AUTO)
 public Long getId() {
  return id;
 }

 @Column(name="name", nullable=false)
 public String getName() {
  return name;
 }

 @Column(name="price", nullable=false, precision=22, scale=0)
 public Double getPrice() {
  return price;
 }

 public void setDescription(String description) {
  this.description = description;
 }

 public void setId(Long id) {
  this.id = id;
 }

 public void setName(String name) {
  this.name = name;
 }

 public void setPrice(Double price) {
  this.price = price;
 }
 
 @OneToMany(mappedBy="item", cascade=CascadeType.ALL)
 public List<BasketItem> getBasketItems() {
  return this.basketItems;
 }

 public void setBasketItems(List<BasketItem> basketItems) {
  this.basketItems = basketItems;
 }
}


  • @Entity declares the class as an entity bean (i.e. a persistent POJO class). @Id declares the identifier property of this entity bean. The other mapping declarations are implicit.
  • @Table is set at the class level; it allows you to define the table, catalog, and schema names for your entity bean mapping. If no @Table is defined the default values are used: the unqualified class name of the entity.


Hibernate Annotation Extensions
Hibernate 3.1 offers a variety of additional annotations that you can mix/match with your EJB 3 (JPA) entities. They have been designed as a natural extension of JPA annotations. I am using a Hibernate annotation in the Basket class to handle the removal of orphans as the current version of JPA doesn't have an annotation that handles this.

Basket.java
@OneToMany(mappedBy="basket", cascade=CascadeType.ALL)
@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
public List<BasketItem> getBasketItems() {
 return basketItems;
}

To empower the EJB3 capabilities, hibernate provides specific annotations that match hibernate features. The org.hibernate.annotations package contains all these annotations extensions. Please refer to the hibernate documentation for more information.

Serializable
One of the other important things to note was that our entity classes implement the interface Serializable. Strictly speaking, this is not a requirement. However, in practice you will normally want your Hibernate objects to be serializable so that they can be (potentially) migrated around a multiprocessor cluster or saved and restored across a web server reboot etc.

Session Factory vs EntityManager
The Session factory is used by the Hibernate sample application to transact with the database whereas the EntityManager is used by the JPA sample application.

1. SessionFactory
The session factory creates Sessions. Usually an application has a single SessionFactory. Threads servicing client requests obtain Sessions from the factory. The Session interface is the main runtime interface between a Java application and Hibernate. The main function of the Session is to offer create, read and delete operations for instances of mapped entity classes.

2. EntityManager
An EntityManager instance is associated with a persistence context. The EntityManager is used to create and remove persistent entity instances, to find entities by their primary key, and to query over entities.


Hibernate utility class vs JPA utility class
I created a utility class that will be used by any class within the Shopping Cart application that requires a hibernate session / EntityManager.

1. Hibernate utility
The class is called HibernateUtil.java and can be found in the com.mydomain.shoppingcart.util package.

2. JPA utility
The class is called JPAUtil.java and can be found in the com.mydomain.shoppingcart.util package.


Data Access Object (DAO's)
A Data Access Object (DAO) is an object that provides an abstract interface to some type of database or persistence mechanism, providing some specific operations without exposing details of the database. The DAO pattern allows data access mechanisms to change independently of the code that uses the data. Compare the DAO's in the Hibernate sample application to the JPA sample application. You will see where the Hibernate session is being used and where JPA's EntityManager is being used. I created two DAO's, one for each of our Entities:
  • ItemDaoImpl – implements ItemDao interface
  • BasketDaoImpl – implements BasketDao interface

Lastly I tied the rest of the pieces together so that our application was using our DAO's now and not just getting back stubbed data.