Showing posts with label tutorials. Show all posts
Showing posts with label tutorials. Show all posts

Thursday, April 8, 2010

Spring Transactions - Sample Applications

Introduction
A while back I created four simple Java applications demonstrating Spring's transaction management implementation and recently thought it would be nice to share them. They may be too simple for most people but for someone new to Spring they may actually be helpful.

If you want to learn about transaction management in Spring then a good place to start is the Spring documentation and for the running examples you can download the spring-transactions-samples.zip Eclipse archive file. The four sample applications are broken down into four of Spring's transaction management abstractions, i.e.:
  • Declarative
    • XML
    • Annotations
  • Programmatic
    • TransactionTemplate
    • PlatformTransactionManager

In the examples that follow I have used the Spring DataSourceTransactionManager implementation as it is linked to a JDBC DataSource. I am using an in-memory database provided by HSQLDB and therefore don't have to do much except define configuration settings for the datasource in the Spring bean configuration file: 

transaction-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-3.0.xsd">
 
 <bean id="testDataSource" class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
  <property name="url" value="jdbc:hsqldb:testdb" />
  <property name="username" value="sa" />
  <property name="password" value="" />
 </bean>
 
 <bean id="transactionManager"
  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="testDataSource" />
 </bean>

</beans>

Declarative - XML
Declarative transaction management is the most common Spring implementation as it has the least impact on application code. The XML declarative approach configures the transaction attributes in a Spring bean configuration file. The sample application for this implementation can be found in the com.mydomain.spring.transaction.declarative.xml package. There are a few simple methods with different transaction settings configured to demonstrate some of the possible scenarios. I recommend running the sample application and viewing the logs to see what Spring prints out. 

xml-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" 
 xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

 <import resource="classpath:transaction-test.xml" />
 
 <bean id="transactionTestService" class="com.mydomain.spring.transaction.declarative.xml.XmlTransactionTestService" />

 <tx:advice id="txAdvice" transaction-manager="transactionManager">
  <tx:attributes>
   <tx:method name="readOnly*" read-only="true" />
   <tx:method name="*" />
  </tx:attributes>
 </tx:advice>

 <aop:config>
  <aop:pointcut id="xmlTransactionTestServiceOperation"
   expression="execution(* com.mydomain.spring.transaction.declarative.xml.XmlTransactionTestService.*(..))" />
  <aop:advisor advice-ref="txAdvice" pointcut-ref="xmlTransactionTestServiceOperation" />
 </aop:config>
</beans>

The <tx:advice/> definition makes the service object TransactionTestService bean transactional and defines all methods starting with 'readOnly' to execute in the context of a read-only transaction, and all other methods to execute with the default transaction semantics.

The <aop:config/> definition ensures that the transactional advice defined by the txAdvice bean executes at the appropriate points in the program.

The above configuration will be used to create a transactional proxy around the object that is created from the transactionTestService bean definition. The proxy will be configured with the transactional advice, so that when an appropriate method is invoked on the proxy, a transaction is started, suspended, marked as read-only, and so on, depending on the transaction configuration associated.

XmlTransactionTestService.java
public class XmlTransactionTestService implements TransactionTestService {
 private final static Log log = LogFactory.getLog(XmlTransactionTestService.class);
 
 public void readOnlyCommitExampleTransaction() {
  log.info("-- XmlTransactionTestService.readOnlyCommitExampleTransaction -- expects transaction commit and read-only");
  // do stuff
 }
 
 public void readOnlyRollbackExampleTransaction() {
  log.info("-- XmlTransactionTestService.readOnlyRollbackExampleTransaction -- expects transaction rollback and read-only");
  // do stuff
  throw new RuntimeException("readOnlyRollbackExampleTransaction Exception");
 }
 
 public void readWriteCommitExampleTransaction() {
  log.info("-- XmlTransactionTestService.readWriteCommitExampleTransaction -- expects transaction commit");
  // do stuff
 }
 
 public void readWriteRollbackExampleTransaction() {
  log.info("-- XmlTransactionTestService.readWriteRollbackExampleTransaction -- expects transaction rollback");
  // do stuff
  throw new RuntimeException("readWriteRollbackExampleTransaction Exception");
 }
}

When you run this example you will see by the logs that method names starting with readOnly execute in the context of a transaction with read-only semantics and that the other methods execute in the context of a transaction with read-write semantics. You will also notice that the transactions will rollback where an exception is thrown otherwise the transaction will commit.

Declarative - Annotations
The annotation declarative approach configures the transaction attributes via annotations in the Java source file. The sample application for this implementation can be found in the com.mydomain.spring.transaction.declarative.annotations package. 

annotations-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" 
    xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
 
 <import resource="classpath:transaction-test.xml" />
 
 <bean id="transactionTestService" class="com.mydomain.spring.transaction.declarative.annotations.AnnotationsTransactionTestService" />

   <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

The definition switches on the transactional behaviour, the rest of the configuration is done via annotations in the Java source.

AnnotationsTransactionTestService.java
public class AnnotationsTransactionTestService implements TransactionTestService {
 private final static Log log = LogFactory.getLog(AnnotationsTransactionTestService.class);

 @Transactional(readOnly = true)
 public void readOnlyCommitExampleTransaction() {
  log.info("-- AnnotationsTransactionTestService.readOnlyCommitExampleTransaction -- expects transaction commit and read-only");
  // do stuff
 }
 
 @Transactional(readOnly = true)
 public void readOnlyRollbackExampleTransaction() {
  log.info("-- AnnotationsTransactionTestService.readOnlyRollbackExampleTransaction -- expects transaction rollback and read-only");
  // do stuff
  throw new RuntimeException("readOnlyRollbackExampleTransaction Exception");
 }
 
 @Transactional
 public void readWriteCommitExampleTransaction() {
  log.info("-- AnnotationsTransactionTestService.readWriteCommitExampleTransaction -- expects transaction commit");
  // do stuff
 }
 
 @Transactional
 public void readWriteRollbackExampleTransaction() {
  log.info("-- AnnotationsTransactionTestService.readWriteRollbackExampleTransaction -- expects transaction rollback");
  // do stuff
  throw new RuntimeException("readWriteRollbackExampleTransaction Exception");
 }
}

When you run this example you will see by the logs that the methods that have the readOnly element set to true for the Transactional annotation execute in the context of a transaction with read-only semantics and that the methods that don't execute in the context of a transaction with read-write semantics. You will also notice that the transactions will rollback where an exception is thrown otherwise the transaction will commit.

Programmatic - TransactionTemplate
This is the recommended approach when using programmatic transaction management. The sample application for this implementation can be found in the com.mydomain.spring.transaction.programmatic.template package. 

template-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-3.0.xsd">
 
 <import resource="classpath:transaction-test.xml" />
 
 <bean id="transactionTestService" class="com.mydomain.spring.transaction.programmatic.template.TemplateTransactionTestService">
  <property name="transactionManager" ref="transactionManager"/>
 </bean>
</beans>

TemplateTransactionTestService.java
public class TemplateTransactionTestService implements TransactionTestService {
 private final static Log log = LogFactory.getLog(TemplateTransactionTestService.class);
 
 private PlatformTransactionManager transactionManager = null;
 
 public PlatformTransactionManager getTransactionManager() {
  return transactionManager;
 }

 public void setTransactionManager(PlatformTransactionManager transactionManager) {
  this.transactionManager = transactionManager;
 }
 
 public void readOnlyCommitExampleTransaction() {
  log.info("-- TemplateTransactionTestService.readOnlyCommitExampleTransaction -- expects transaction commit and read-only");
  final TransactionTemplate tt = new TransactionTemplate(transactionManager);
  tt.setReadOnly(true);
  tt.execute(new TransactionCallbackWithoutResult() {
   public void doInTransactionWithoutResult(TransactionStatus status) {
    log.info("-- doInTransactionWithoutResult -- expects transaction commit");
    // do stuff
   }
  });
 }
 
 public void readOnlyRollbackExampleTransaction() {
  log.info("-- TemplateTransactionTestService.readOnlyRollbackExampleTransaction -- expects transaction rollback and read-only");
  final TransactionTemplate tt = new TransactionTemplate(transactionManager);
  tt.setReadOnly(true);
  tt.execute(new TransactionCallbackWithoutResult() {
   public void doInTransactionWithoutResult(TransactionStatus status) {
    log.info("-- doInTransactionWithoutResult -- expects transaction rollback");
    // do stuff
    status.setRollbackOnly();
   }
  });
 }
 
 public void readWriteCommitExampleTransaction() {
  log.info("-- TemplateTransactionTestService.readWriteCommitExampleTransaction -- expects transaction commit");
  final TransactionTemplate tt = new TransactionTemplate(transactionManager);
  tt.execute(new TransactionCallbackWithoutResult() {
   public void doInTransactionWithoutResult(TransactionStatus status) {
    log.info("-- doInTransactionWithoutResult -- expects transaction commit");
    // do stuff
   }
  });
 }
 
 public void readWriteRollbackExampleTransaction() {
  log.info("-- TemplateTransactionTestService.readWriteRollbackExampleTransaction -- expects transaction rollback");
  final TransactionTemplate tt = new TransactionTemplate(transactionManager);
  tt.execute(new TransactionCallbackWithoutResult() {
   public void doInTransactionWithoutResult(TransactionStatus status) {
    log.info("-- doInTransactionWithoutResult -- expects transaction rollback");
    // do stuff
    status.setRollbackOnly();
   }
  });
 }
}

Programmatic - PlatformTransactionManager
ptm-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-3.0.xsd">
 
 <import resource="classpath:transaction-test.xml" />
 
 <bean id="transactionTestService" class="com.mydomain.spring.transaction.programmatic.ptm.PtmTransactionTestService">
  <property name="transactionManager" ref="transactionManager"/>
 </bean>
</beans>

PtmTransactionTestService.java
public class PtmTransactionTestService implements TransactionTestService {
private final static Log log = LogFactory.getLog(PtmTransactionTestService.class);
 
 private PlatformTransactionManager transactionManager = null;
 
 public PlatformTransactionManager getTransactionManager() {
  return transactionManager;
 }

 public void setTransactionManager(PlatformTransactionManager transactionManager) {
  this.transactionManager = transactionManager;
 }
 
 public void readOnlyCommitExampleTransaction() {
  log.info("-- PtmTransactionTestService.readOnlyCommitExampleTransaction -- expects transaction commit and read-only");
  DefaultTransactionDefinition def = new DefaultTransactionDefinition();
  def.setReadOnly(true);
  TransactionStatus status = transactionManager.getTransaction(def);
  // do stuff
  transactionManager.commit(status);
 }
 
 public void readOnlyRollbackExampleTransaction() {
  log.info("-- PtmTransactionTestService.readOnlyRollbackExampleTransaction -- expects transaction rollback and read-only");
  DefaultTransactionDefinition def = new DefaultTransactionDefinition();
  def.setReadOnly(true);
  TransactionStatus status = transactionManager.getTransaction(def);
  // do stuff
  transactionManager.rollback(status);
 }
 
 public void readWriteCommitExampleTransaction() {
  log.info("-- PtmTransactionTestService.readWriteCommitExampleTransaction -- expects transaction commit");
  DefaultTransactionDefinition def = new DefaultTransactionDefinition();
  TransactionStatus status = transactionManager.getTransaction(def);
  // do stuff
  transactionManager.commit(status);
 }
 
 public void readWriteRollbackExampleTransaction() {
  log.info("-- PtmTransactionTestService.readWriteRollbackExampleTransaction -- expects transaction rollback");
  DefaultTransactionDefinition def = new DefaultTransactionDefinition();
  TransactionStatus status = transactionManager.getTransaction(def);
  // do stuff
  transactionManager.rollback(status);
 }
}

Programmatic or declarative transaction management?
"Programmatic transaction management is usually a good idea only if you have a small number of transactional operations. For example, if you have a web application that require transactions only for certain update operations, you may not want to set up transactional proxies using Spring or any other technology. In this case, using the TransactionTemplate may be a good approach. Being able to set the transaction name explicitly is also something that can only be done using the programmatic approach to transaction management. 

On the other hand, if your application has numerous transactional operations, declarative transaction management is usually worthwhile. It keeps transaction management out of business logic, and is not difficult to configure. When using the Spring Framework, rather than EJB CMT, the configuration cost of declarative transaction management is greatly reduced."

Friday, March 19, 2010

Shopping Cart Web Application - Bean Validation

Introduction
In my previous blog entry I wrote about adding security to the shopping cart web application. Part of the change I made to the application was adding a form to register users and a form to add and update items. It made sense to add validation to the fields so that we could maintain the integrity of our data.

I currently maintain two different versions of the application:
  • ShoppingCartSecurity.zip – A standard web application that runs off Tomcat 6 and is built with Hibernate, Spring, JPA and RichFaces. This is an Eclipse archive file that contains two Eclipse projects. 
  • ShoppingCartGF.zip – A JEE application that runs off GlassFish vs 3 and is built with EJB 3.0, JPA and RichFaces.

There are a number of different approaches one can take when doing validation. A common approach is using client side form validation which uses JavaScript to validate the form fields. There is no round trip to the server so the validation is nice and fast. The jQuery Javascript library has a nice plugin to use if you are interested in this approach. Even though client side validation is nice it isn't essential however server side validation is not an option and should be implemented to ensure data integrity. For the shopping cart application I decided to only use server side validation so that I was using a common validation implementation. In order to get the same user experience as client side validation I chose to use the Ajax JSF RichFaces library.

The validation  framework I have chosen to use is the standard validation framework (JSR 303: Bean Validation) implemented in Java EE 6. As of version 4.x Hibernate Validator is based on a new code base which is the reference implementation for JSR 303.

"JSR 303 defines a metadata model and API for JavaBean validation. The default metadata source is annotations, with the ability to override and extend the meta-data through the use of XML validation descriptors. The API is not tied to a specific application tier or programming model. It is specifically not tied to either the web tier or the persistence tier, and is available for both server-side application programming, as well as rich client Swing application developers."

What we will cover
  • Defining constraints
  • Custom validation
  • Spring injection into custom validators
  • Validating constraints
  • RichFaces Ajax validation for JSF inputs


Constraints
Constraints in Bean Validation are expressed via Java annotations. There are three different types of constraint annotations, namely: field, property, and class-level annotations. An example of property annotations can be seen in the User class:

@Column(name="username", nullable=false, unique=true)
@NotEmpty
@Length(min=4, max=12)
@Pattern(regexp="^[a-zA-Z\\d_]{4,12}$", message="{validator.username.invalid}")
@Username(message="{validator.username}")
public String getUsername() {
 return username;
}

The getter method for the username property specifies the following validation annotations:
  • @NotEmpty – The username cannot be null or empty.
  • @Length(min=4, max=12) – The length of the username must be at least 4 characters long and no more than 12 characters long.
  • @Pattern(regexp="^[a-zA-Z\\d_]{4,12}$", message="{validator.username.invalid}") – Match a regular expression. The username must contain alphanumeric characters. The default message is overridden with a key mapped to a message in the validation resource file. 
  • @Username(message="{validator.username}") – Custom validator to compares the usernames already stored in the database to check for duplicates.

An example of where I have used class-level annotation validation can be found in the Register.java JSF backing bean class:

@FieldMatch.List({
 @FieldMatch(first="password", second="confirmedPassword",
   message="{validator.fieldmatch.password}")
  })
public class Register extends BasePage {
 private Validator validator;
 private String password;
 private String confirmedPassword;

 @NotEmpty
 @Length(min=6, max=12)
 @Pattern(regexp = "(?=.*\\d)(?=.*[a-zA-Z]).{6,12}", message = "{validator.password.insecure}")
 public String getPassword() {
  return password;
 }

 public void validateUsername() {
  Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(getUser(), "username");
  if (constraintViolations.size() > 0) {
   String msg = constraintViolations.iterator().next().getMessage();
   addError(getUiUsername().getClientId(getFacesContext()), msg);
  }
 }
 
 public void validatePassword() {
  Set<ConstraintViolation<Register>> constraintViolations = validator.validateProperty(this, "password");
  if (constraintViolations.size() > 0) {
   String msg = constraintViolations.iterator().next().getMessage();
   addError(getUiPassword().getClientId(getFacesContext()), msg);
  }
 }
 
 public void validateConfirmedPassword() {
  Set<ConstraintViolation<Register>> constraintViolations = validator.validate(this);
  if (constraintViolations.size() > 0) {
   ConstraintViolation<Register> cv = constraintViolations.iterator().next();
   if (cv.getMessageTemplate().equals("{validator.fieldmatch.password}")) {
    addError(getUiConfirmedPassword().getClientId(getFacesContext()), cv.getMessage());    
   }
  }
 }
 
 ...
 
}

  • @FieldMatch – Custom cross field validation class-level annotation used to compare the values of two fields, namely password and confirmed password. 
  • @NotEmpty – The password cannot be null or empty.
  • @Length(min=6, max=12) – The length of the password must be at least 6 characters long and no more than 12 characters long.
  • @Pattern(regexp = "(?=.*\\d)(?=.*[a-zA-Z]).{6,12}", message="{validator.password.insecure}") – Match a regular expression. The password must contain alphanumeric characters. The default message is overridden with a key mapped to a message in the validation resource file. 

Custom Validators
As mentioned above I have two custom validators, namely Username and FieldMatch. Creating a custom validator is actually very simple and requires the following three steps:

  • Create a constraint annotation
  • Implement a validator
  • Define a default error message

I won’t go over this in too much detail as the Hibernate Validator documentation is pretty good and covers this nicely.

Username constraint annotation (Username.java)

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy=UsernameValidator.class)
public @interface Username {
 String message() default "Username already exists";
 Class<?>[] groups() default {};
 Class<? extends Payload>[] payload() default {};
}

Username validator (UsernameValidator.java)

public class UsernameValidator implements ConstraintValidator<Username, Object> {
 @Autowired
 private UserDao userDao;

 public void setUserDao(UserDao userDao) {
  this.userDao = userDao;
 }

 public void initialize(Username parameters) {
 }

 public boolean isValid(final Object value, ConstraintValidatorContext context) {
  try {
   User user = userDao.findByUsername((String) value);
   if (user == null) {
    return true;
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
  return false;
 }
}

Spring injection
You will notice I am injecting the UserDao class into this validator using Springs @Autowired annotation. This is made possible thanks to Spring’s LocalValidatorFactoryBean class.

"By default, the LocalValidatorFactoryBean configures a SpringConstraintValidatorFactory that uses Spring to create ConstraintValidator instances. This allows your custom ConstraintValidators to benefit from dependency injection like any other Spring bean."

I only needed to add the following line of code to the shoppingcart-database.xml Spring bean configuration file in order to use the SpringConstraintValidatorFactory:

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

The Register.java JSF backing bean mentioned earlier gets a reference to the Spring created Validator by declaring the managed property in the faces-config.xml:

<managed-bean>
 <managed-bean-name>pc_Register</managed-bean-name>
 <managed-bean-class>com.mydomain.shoppingcart.view.Register</managed-bean-class>
 <managed-bean-scope>request</managed-bean-scope>
 <managed-property>
  <property-name>shoppingViewHelper</property-name>
  <value>#{shoppingViewHelper}</value>
 </managed-property>
 <managed-property>
  <property-name>validator</property-name>
  <value>#{validator}</value>
 </managed-property>
</managed-bean>

ValidationMessages.properties
I created a ValidationMessages.properties file and saved it in my src folder of my project. Hibernate Validator uses this file to retrieve the messages used by the validators.

Tying it together with the user interface
The login-form.jspx page includes a form for registering users. Instead of explaining each input field I am only going to step through one of them (username) and explain the validation process for it:

<h:inputText id="usrnameInTxt" binding="#{pc_Register.uiUsername}" value="#{pc_Register.user.username}" label="usrnameOutTxt" tabindex="1">
 <a4j:support id="usrnameSpt" event="onblur" reRender="usrnameMsg" limitToList="true" action="#{pc_Register.validateUsername}" />
</h:inputText>
<rich:message id="usrnameMsg" for="usrnameInTxt" errorClass="error" />

The a4j:support tag is a RichFaces tag that provides Ajax support to JSF input fields. Here it defines that the validateUsername method in the Register backing bean will be invoked when the onblur event of the input text field is triggered.

public void validateUsername() {
 Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(getUser(), "username");
 if (constraintViolations.size() > 0) {
  String msg = constraintViolations.iterator().next().getMessage();
  addError(getUiUsername().getClientId(getFacesContext()), msg);
 }
}

As you can see from the above code the validator class in the validateUsername method invokes the validateProperty method. The single property username is validated and if any constraint violations are raised an error message is added to the FacesContext.

The RichFaces rich:message tag behaves the same way as the standard JSF h:message tag except it will auto re-render itself after an Ajax request.

RichFaces Ajax Validator
RichFaces also has an Ajax validator tag that ties nicely into Hibernate Validator. I use this tag in the Items Admin modal panel of the items.jspx page.

<h:inputText id="nameInTxt" 
 value="#{pc_Items.selectedItem.name}"
 label="nameOutTxt" tabindex="1">
 <rich:ajaxValidator event="onblur" />
</h:inputText>
<rich:message id="nameMsg" for="nameInTxt" errorClass="error" />

As you can see there are no a4j:support tags or validation methods that get called. RichFaces will create its own Validator instance and call the validate property methods automatically for you. This works pretty nicely in the above example however for the registration form we are not using this tag because the validator is created for us by the Spring LocalValidatorFactoryBean class.


Registration screen shot



Thursday, March 18, 2010

Shopping Cart Web Application - Security

Introduction
Those of you who are familiar with the shopping cart application tutorial will be pleased to know I have finally added security to it. It was never my intention to add security to the shopping cart application as I felt it was a little out of the scope of what I was trying to achieve. However the application would never been complete unless security was added to it.

I currently maintain two different versions of the shopping cart application:
  1. ShoppingCartSecurity.zip – A standard web application that runs off Tomcat 6 and is built with Hibernate, Spring, JPA and RichFaces. This is an Eclipse archive file that contains two Eclipse projects. You should be able to import these projects into your Eclipse environment.
  2. ShoppingCartGF.zip – A JEE application that runs off GlassFish vs 3 and is built with EJB 3.0, JPA and RichFaces. This is also an Eclipse archive file that contains three Eclipse projects. You should be able to import these projects into your Eclipse environment as well.
If you would like to compile and deploy the above mentioned applications you will need the libraries that they reference. I haven't included the libraries in the downloads, however I have provided links to all the libraries I have used in the previous shopping cart tutorials. I am not going to mention all of them here so you will need to go through each tutorial in order to get them. Over and above those libraries you will also need the below mentioned ones as these are specific to this version of the application:

ShoppingCartSecurity application

ShoppingCartGF application


What we will cover
  • Form-based authentication
  • Deployment configuration
  • Login form
  • Security realms
  • Using authentication with SSL
  • New features added to the shopping cart application 


Form-based authentication
The most common authentication mechanism and the one I chose to implement for the shopping cart application is called form-based authentication. Users can navigate through unprotected areas of the website without requiring a password. Only when the user tries to access a protected page will they be redirected to  a login page.


  1. A client requests access to a protected resource.
  2. If the client is unauthenticated, the server redirects the client to a login page.
  3. The client submits the login form to the server.
  4. If the login succeeds, the server redirects the client to the resource. If the login fails, the client is redirected to an error page.


Deployment Configuration
To configure our application for form-based authentication we need to define the authentication method in our web deployment descriptor, which resources are protected and what security roles are used. Below is a snippet from the web deployment descriptor that depicts these changes:

<security-constraint>
 <web-resource-collection>
  <web-resource-name>protected</web-resource-name>
  <url-pattern>/secure/*</url-pattern>
  <http-method>GET</http-method>
  <http-method>POST</http-method>
  <http-method>HEAD</http-method>
  <http-method>PUT</http-method>
  <http-method>OPTIONS</http-method>
  <http-method>TRACE</http-method>
  <http-method>DELETE</http-method>
 </web-resource-collection>
 <auth-constraint>
  <role-name>administrator</role-name>
  <role-name>customer</role-name>
 </auth-constraint>
</security-constraint>
<login-config>
 <auth-method>FORM</auth-method>
 <realm-name>shoppingCartJDBCRealm</realm-name>
 <form-login-config>
  <form-login-page>/login.faces</form-login-page>
  <form-error-page>/error.faces</form-error-page>
 </form-login-config>
</login-config>
<security-role>
 <description>Administrators role</description>
 <role-name>administrator</role-name>
</security-role>
<security-role>
 <description>Customers role</description>
 <role-name>customer</role-name>
</security-role>

Security constraint
The security-constraint element defines the access privileges to a collection of resources using their URL mapping.
  • web-resource-collection - used to identify the resources in a web application to which a security constraint applies. In the above example the URL pattern /secure/* specifies that all resources in this application under the secure folder are protected.
  • auth-constraint - indicates the user roles that should be permitted access to this resource collection. 

Login config
The login-config element defines the authentication method (namely form-based authentication) as well as the page that will be displayed when an unauthenticated user tries to access secure content and the page that will be displayed when login fails. For the GlassFish version of the application the realm name is defined to specify which realm configured on the server should be used when authenticating users.

Security role
The security-role element specifies the role a user can belong to.

Login form
The login page can be an HTML page, a JSP page, or a servlet, and it must return an HTML page containing a form that conforms to specific naming conventions. The login page needs to contain a form with j_security_check as its action as well as a text input box called j_username and a password input box called j_password. These are the input names that need to be used in order for the application server to process the Form authentication. An example of how this is implemented can be seen in the login-form.jspx page:

<h:panelGrid id="loginGrd" columns="2">
 <h:outputText id="usernameOutTxt" value="#{msg.login_txt_username}" />
 <input id="usernameInTxt" type="text" name="j_username" />
 <h:outputText id="passwordOutTxt" value="#{msg.login_txt_password}" />
 <input id="passwordInTxt" type="password" name="j_password" />
 <f:facet name="footer">
  <input type="submit" value="#{msg.btn_login}" />
 </f:facet>
</h:panelGrid>

Realm
A realm is a repository of user names and passwords that identify valid users of a web application along with the list of roles associated with each valid user. There are a number of different realms one can configure, in our example I chose to configure a JDBC realm where the users name and authentication details are stored in a database. Each application server is unique in its configuring of realms. Below are the steps I took to configure Tomcat and GlassFish:

Tomcat
In order to add a realm to Tomcat you need to edit the server.xml file, for our example I added the following realm to the server.xml:

<Realm className="org.apache.catalina.realm.JDBCRealm" 
   connectionName="sa" 
   connectionPassword="" 
   connectionURL="jdbc:hsqldb:hsql://localhost:9001/shoppingcart" 
   debug="99" 
   digest="MD5" 
   driverName="org.hsqldb.jdbcDriver" 
   roleNameCol="role_name" 
   userCredCol="password" 
   userNameCol="username" 
   userRoleTable="user_role" 
   userTable="users"/>

GlassFish
To configure a realm in GlassFish login to the GlassFish administration console and navigate to: Configuration -> Security -> Realms. Click on the new button and complete the form as shown in the screen shot below:


This assumes a datasource with the JNDI name jdbc/__shoppingcart has already been configured.

GlassFish requires its own deployment descriptor (sun-web.xml) to be configured in order to map the roles defined in the web applications web.xml file to the groups defined on the application server:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD 
GlassFish Application Server 3.0 Servlet 3.0//EN" 
"http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd">
<sun-web-app>
 <security-role-mapping>
  <role-name>customer</role-name>
  <group-name>customer</group-name>
 </security-role-mapping>
 <security-role-mapping>
  <role-name>administrator</role-name>
  <group-name>administrator</group-name>
 </security-role-mapping>
</sun-web-app>

Using Authentication with SSL
Form-based authentication alone is not particularly secure, passwords sent between a client and a server on an unprotected session can be viewed and intercepted by third parties. In order to prevent this from happening you would need to configure your connections to run over an SSL (Secure Socket Layer) protected session. SSL is a technology which allows web browsers and web servers to communicate over a secured connection. This means that the data being sent is encrypted by one side, transmitted and then decrypted by the other side before processing. 

Usually you wouldn't have to configure your application server for SSL as you most likely would have a primary web server running that is used to handle all requests and responses from the browser to the server. The web server will therefore be configured to handle the SSL connections from the users. This web server will negotiate all SSL related functionality and then pass on any requests destined for the application server only after decrypting those requests. 

I haven't configured the shopping cart application to run over SSL. If you would like to learn more here are some useful links to get you started:


New features added to the shopping cart application 
The following additional features not mentioned above were added to the shopping cart application
  1. Three new entity classes, namely User, Role and UserRole
  2. User registration
  3. Item administration
  4. Once logged in an administrator can maintain the items list by adding, editing and removing items


Additional settings
Tomcat
  1. In order to get JSTL to work in Tomcat 6 I followed the instructions outlined in this tutorial.
  2. In the previous examples of the shopping cart application I used an in-memory database. However in this version I am not. The reason is because Tomcat would sometimes not find any user results and sometimes it would. It is a mystery to me as the Tomcat server and my application runs within the same JVM so it should be using the same database right? I lost patience and reverted to a file based database. I use an ant build script to start and stop the HSQL database. The file is called db-man-build.xml and can be located in the build folder. 
  3. The applications administrator's user name is 'admin' and the password is 'admin'. These values along with the default collection of items will automatically be imported into the shoppingcart database on application startup. 

GlassFish
  1. I configured a Derby database to use with the GlassFish version of the application. You can start and stop the Derby database by running the asadmin start-database or asadmin stop-database commands from the bin directory in the GlassFish installation directory. 
  2. The database will need to be pre-populated with data manually as this doesn't get done automatically by the application. The import sql script can be located in src folder of the shopping-cart-core-gf project. 


Screen shots
Registration modal with login form in the background


Items administration modal page with the landing page in the background


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>