JBoss Web Framework Kit 1.2

Spring Developer Guide

for use with JBoss Web Framework Kit

Edition 1.2.0

Marius Bogoevici

Red Hat

Edited by

Rebecca Newton

Red Hat

Legal Notice

Copyright © 2011 Red Hat, Inc.
This document is licensed by Red Hat under the Creative Commons Attribution-ShareAlike 3.0 Unported License. If you distribute this document, or a modified version of it, you must provide attribution to Red Hat, Inc. and provide a link to the original. If the document is modified, all Red Hat trademarks must be removed.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, MetaMatrix, Fedora, the Infinity Logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat Software Collections is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack Logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.

Abstract

An introduction to developing Spring-based application for the JBoss Platform.
Preface
1. Document Conventions
1.1. Typographic Conventions
1.2. Pull-quote Conventions
1.3. Notes and Warnings
2. Getting Help and Giving Feedback
2.1. Do You Need Help?
2.2. Give us Feedback
1. Introduction and Download
1.1. Obtaining Spring
1.2. How to Find Spring Jars
I. Getting Started Example
2. Getting Started Example Introduction
2.1. Prerequisites
2.2. The Example
3. Task One: Creating the Maven Project Structure
3.1. Create the Maven Project Structure
3.2. Dependencies
3.2.1. Using Dependencies
4. Task Two: Create the Source Code
4.1. Setting up Persistence
5. Task Three: Add the Spring Configuration Files
6. Task Four: Run the Example
II. Best Practices And Integration Guidelines
7. Best Practices
7.1. Setting Up Data Access
7.1.1. Database Access Through Managed Datasources
7.1.2. Hibernate SessionFactory
7.2. Using JPA
7.2.1. PersistenceUnit Deployed by the Container
7.2.2. PersistenceUnit Created by Spring
7.2.3. @PersistenceContext and @PersistenceUnit Injection
7.3. Messaging (JMS) Integration
7.4. Transaction Management
7.5. EJB Integration
7.5.1. Injecting Spring Beans Into EJBs
7.5.2. Accessing EJBs from Spring Beans
III. Migration
8. Migrating applications to JBoss EAP and EWP
8.1. General Migration Mechanics
8.2. Spring's PetClinic
8.3. Spring Travel
A. Content of pom.xml files for the examples
A.1. Content of pom.xml File for the Getting Started Example
A.2. Modified Starting pom.xml File for Pet Clinic Migration
B. Setting up JBDS
B.1. Setting up Maven for m2eclipse
B.2. Adding a JBoss Enterprise Application Instance
C. Revision History
Index

Preface

1. Document Conventions

This manual uses several conventions to highlight certain words and phrases and draw attention to specific pieces of information.
In PDF and paper editions, this manual uses typefaces drawn from the Liberation Fonts set. The Liberation Fonts set is also used in HTML editions if the set is installed on your system. If not, alternative but equivalent typefaces are displayed. Note: Red Hat Enterprise Linux 5 and later include the Liberation Fonts set by default.

1.1. Typographic Conventions

Four typographic conventions are used to call attention to specific words and phrases. These conventions, and the circumstances they apply to, are as follows.
Mono-spaced Bold
Used to highlight system input, including shell commands, file names and paths. Also used to highlight keys and key combinations. For example:
To see the contents of the file my_next_bestselling_novel in your current working directory, enter the cat my_next_bestselling_novel command at the shell prompt and press Enter to execute the command.
The above includes a file name, a shell command and a key, all presented in mono-spaced bold and all distinguishable thanks to context.
Key combinations can be distinguished from an individual key by the plus sign that connects each part of a key combination. For example:
Press Enter to execute the command.
Press Ctrl+Alt+F2 to switch to a virtual terminal.
The first example highlights a particular key to press. The second example highlights a key combination: a set of three keys pressed simultaneously.
If source code is discussed, class names, methods, functions, variable names and returned values mentioned within a paragraph will be presented as above, in mono-spaced bold. For example:
File-related classes include filesystem for file systems, file for files, and dir for directories. Each class has its own associated set of permissions.
Proportional Bold
This denotes words or phrases encountered on a system, including application names; dialog box text; labeled buttons; check-box and radio button labels; menu titles and sub-menu titles. For example:
Choose SystemPreferencesMouse from the main menu bar to launch Mouse Preferences. In the Buttons tab, select the Left-handed mouse check box and click Close to switch the primary mouse button from the left to the right (making the mouse suitable for use in the left hand).
To insert a special character into a gedit file, choose ApplicationsAccessoriesCharacter Map from the main menu bar. Next, choose SearchFind… from the Character Map menu bar, type the name of the character in the Search field and click Next. The character you sought will be highlighted in the Character Table. Double-click this highlighted character to place it in the Text to copy field and then click the Copy button. Now switch back to your document and choose EditPaste from the gedit menu bar.
The above text includes application names; system-wide menu names and items; application-specific menu names; and buttons and text found within a GUI interface, all presented in proportional bold and all distinguishable by context.
Mono-spaced Bold Italic or Proportional Bold Italic
Whether mono-spaced bold or proportional bold, the addition of italics indicates replaceable or variable text. Italics denotes text you do not input literally or displayed text that changes depending on circumstance. For example:
To connect to a remote machine using ssh, type ssh username@domain.name at a shell prompt. If the remote machine is example.com and your username on that machine is john, type ssh john@example.com.
The mount -o remount file-system command remounts the named file system. For example, to remount the /home file system, the command is mount -o remount /home.
To see the version of a currently installed package, use the rpm -q package command. It will return a result as follows: package-version-release.
Note the words in bold italics above — username, domain.name, file-system, package, version and release. Each word is a placeholder, either for text you enter when issuing a command or for text displayed by the system.
Aside from standard usage for presenting the title of a work, italics denotes the first use of a new and important term. For example:
Publican is a DocBook publishing system.

1.2. Pull-quote Conventions

Terminal output and source code listings are set off visually from the surrounding text.
Output sent to a terminal is set in mono-spaced roman and presented thus:
books        Desktop   documentation  drafts  mss    photos   stuff  svn
books_tests  Desktop1  downloads      images  notes  scripts  svgs
Source-code listings are also set in mono-spaced roman but add syntax highlighting as follows:
package org.jboss.book.jca.ex1;

import javax.naming.InitialContext;

public class ExClient
{
   public static void main(String args[]) 
       throws Exception
   {
      InitialContext iniCtx = new InitialContext();
      Object         ref    = iniCtx.lookup("EchoBean");
      EchoHome       home   = (EchoHome) ref;
      Echo           echo   = home.create();

      System.out.println("Created Echo");

      System.out.println("Echo.echo('Hello') = " + echo.echo("Hello"));
   }
}

1.3. Notes and Warnings

Finally, we use three visual styles to draw attention to information that might otherwise be overlooked.

Note

Notes are tips, shortcuts or alternative approaches to the task at hand. Ignoring a note should have no negative consequences, but you might miss out on a trick that makes your life easier.

Important

Important boxes detail things that are easily missed: configuration changes that only apply to the current session, or services that need restarting before an update will apply. Ignoring a box labeled 'Important' will not cause data loss but may cause irritation and frustration.

Warning

Warnings should not be ignored. Ignoring warnings will most likely cause data loss.

2. Getting Help and Giving Feedback

2.1. Do You Need Help?

If you experience difficulty with a procedure described in this documentation, visit the Red Hat Customer Portal at http://access.redhat.com. Through the customer portal, you can:
  • search or browse through a knowledgebase of technical support articles about Red Hat products.
  • submit a support case to Red Hat Global Support Services (GSS).
  • access other product documentation.
Red Hat also hosts a large number of electronic mailing lists for discussion of Red Hat software and technology. You can find a list of publicly available mailing lists at https://www.redhat.com/mailman/listinfo. Click on the name of any mailing list to subscribe to that list or to access the list archives.

2.2. Give us Feedback

If you find a typographical error, or know how this guide can be improved, we would love to hear from you. Submit a report in Bugzilla against the product JBoss Web Framework Kit 1 and the component doc-Spring-Developer_Guide. The following link will take you to a pre-filled bug report for this product: http://bugzilla.redhat.com/.
Fill out the following template in Bugzilla's Description field. Be as specific as possible when describing the issue; this will help ensure that we can fix it quickly.
Document URL:


Section Number and Name:


Describe the issue:


Suggestions for improvement:


Additional information:


Be sure to give us your name so that you can receive full credit for reporting the issue.

Chapter 1. Introduction and Download

The Spring Framework is a flexible environment for developing enterprise applications. A number of choices are available for accessing middleware services.
JBoss is a feature-rich application server, which provides a complex set of middleware services. Spring developers can take advantage of those services by opting to use the dedicated Java EE integration features of Spring.
This guide is divided into three parts:
  • Getting Started Example
  • Best Practices and Integration Guidelines
  • Migrating Spring Applications to JBoss
Please see Section 1.1, “Obtaining Spring” for download information.

1.1. Obtaining Spring

A certified version of Spring can be obtained in the following ways:
  • Download it from the Spring Framework site;
  • Download it from a public repository (Maven or Ivy).
The following versions of the Spring Framework are certified:
  • 2.5.6.SEC01
  • 3.0.2.RELEASE
Instructions on how to download and to set up repositories for using the community versions of Spring can be found in the Spring Reference documentation . While the instructions above have been written taking Spring 3 into consideration, they are applicable to version 2.5.6.SEC01 as well.

1.2. How to Find Spring Jars

The downloaded distribution of the Spring Framework may not include the dependencies Spring requires to integrate with third party frameworks. JBoss Web Framework Kit provides many of this dependencies.
The Spring JARs are found in the /dist folder of the downloaded distribution.
The AOP Alliance APIs and AspectJ dependencies are other useful dependencies to include.

Part I. Getting Started Example

Chapter 2. Getting Started Example Introduction

This chapter uses JBoss Developer Studio to develop a simple Spring Model-View-Conroller (MVC) web application on JBoss Enterprise Application Platform.

2.1. Prerequisites

These are the programs and versions used in this example:
  • Maven 3.0.3
    This is optional, and is only used for maven-based examples.
  • Spring 3.0.5.RELEASE
  • JBoss Developer Studio 4 with the m2eclipse plugin.
    See Appendix B for JBoss Developer Studio configuration details.
  • JBoss Enterprise Application Platform 5.1.1
Throughout this guide, $EAP_HOME represents the top-level directory of the extracted distribution. This is usually jboss-eap-5.1.
<profile> represents the JBoss Enterprise Application Platform profile the application is launched with. This is usually defaut. You will find this under jboss-eap-5.1/jboss-as/server/<profile>.

2.2. The Example

This example is a web-based application that includes access to a database. In this Hello World scenario, the user is asked to introduce their username in a web form. The greeting message will contain their full name, which is extracted from a simple database.
This demonstrates:
  • The general project structure of a Spring-based web application;
  • A simple set of domain classes, MVC controllers, and web pages;
  • The data infrastructure configuration (including database, JPA and transactions) for running Spring applications in JBoss.
The following tasks are explored in this example:
  • creating a Maven project infrastructure, including adding dependencies
  • adding the source code
  • adding the Spring configuration files
  • run the example

Chapter 3. Task One: Creating the Maven Project Structure

If the m2eclipse plugin is installed, using JBoss Developer Studio to create a Maven-based web application is fairly simple.
The m2eclipse plugin integrates Maven with JBoss Developer Studio.

Unsupported Plugin

Although the m2eclipse plugin is used in this example, it is not currently supported with your JBoss subscription. Support for Maven and/or the m2eclipse plugin is planned for future releases of JBoss Developer Studio.
Use this website to download and install m2eclipse: m2eclipse plugin
The following are the minimum requirements for the examples in this document.
  • From the Core update site (Core Update):
    • Install "Maven Integration for Eclipse (Required)"
  • From the Extras update site (Extras Update):
    • Install "Maven Integration for WTP"
See Appendix B, Setting up JBDS for configuration options.

3.1. Create the Maven Project Structure

Maven projects all have a standard structure for file locations. Use this procedure to create a standard Maven project with JBoss Developer Studio using the m2eclipse plugin.

Procedure 3.1. Maven Project with m2eclipse

  1. Open JBoss Developer Studio.
  2. The program asks you where to create the project. Click Next to use the default file, Workspace, or choose your own.
  3. In the top left hand corner, click FileNewProject
  4. Double click Maven
  5. Choose Maven Project from the dropdown box.
  6. Click Next
  7. Do not tick the Create a Simple Project checkbox, as an archetype is required for the example.
    Click Next
  8. Choose maven-archetype-webapp
  9. Click Next
  10. Enter the Group ID, Artifact ID, and version.
    Group ID
    org.jboss.spring.getting.started
    Artifact ID
    getting-started
    Version
    1.0
    The package name is automatically set to org.jboss.spring.getting_started.
  11. Click Finish
    Result
    Your project is created.
See Section 3.2, “Dependencies” for information on the dependencies required to run the project.
Java Source Folder
The Java source folder separates Java source files from other kinds of files. The folder is not always created automatically. Follow Procedure 3.2, “Create a Java Source Folder” to create one manually.

Procedure 3.2. Create a Java Source Folder

  1. Open the getting-started example with JBoss Developer Studio.
  2. Right click on the project and then NewSource Folder
  3. Enter the name of your project; in this case, getting-started.
  4. In the space for Folder Name, enter src/main/java
  5. Click Finish
    Result
    A Java source file is created.
Spring Project Nature
Adding the Spring Project nature is not a requirement, but enables integration with the Spring IDE. This includes visualizing your application context definition, and syntactical and semantical checks.
Use Procedure 3.3, “Add the Spring Project Nature” to enable integration with the Spring IDE.

Procedure 3.3. Add the Spring Project Nature

  1. Right click on the project in the left hand menu to bring up dropdown box.
  2. Select Spring Tools
  3. Click Add Spring Project Nature

3.2. Dependencies

The project relies on dependencies. These are detailed in Table 3.1, “Required Dependencies”. Use Procedure 3.4, “Adding Dependencies via JBoss Developer Studio” to add them to your project.

Table 3.1. Required Dependencies

Dependency Maven Identifier Version Scope
Hibernate Core org.hibernate:hibernate-core 3.3.0.GA provided
Hibernate Entity Manager org.hibernate:hibernate-entitymanager 3.4.0.GA provided
Standard Taglibs taglibs:standard 1.1.2 compile
Commons Logging commons-logging:commons-logging 1.1.1 compile
AOP Alliance API aopalliance:aopalliance 1.0 compile
Spring modules
  • org.springframework:spring-aop
  • org.springframework:spring-asm
  • org.springframework:spring-expression
  • org.springframework:spring-beans
  • org.springframework:spring-context
  • org.springframework:spring-context-support
  • org.springframework:spring-tx
  • org.springframework:spring-core
  • org.springframework:spring-jdbc
  • org.springframework:spring-orm
  • org.springframework:spring-web
  • org.springframework:spring-webmvc
3.0.5.RELEASE compile

3.2.1. Using Dependencies

There are two ways to add dependencies to your project:
  • within JBoss Developer Studio
  • within the pom.xml
To add dependencies via pom.xml, copy the dependencies from Appendix A, Content of pom.xml files for the examples to pom.xml.
pom.xml is located within the top-level folder of your project; workspace/getting-started, for example.
Use Procedure 3.4, “Adding Dependencies via JBoss Developer Studio” to add dependencies within JBoss Developer Studio.

Procedure 3.4. Adding Dependencies via JBoss Developer Studio

  1. Open your getting-started project in JBoss Developer Studio.
  2. Click on the arrow next to your project in the folder list on the left. This expands the folder.
  3. If the folder target is not expanded, click on the arrow to expand it.
  4. Double click pom.xml underneath target
    Result
    JBoss Developer Studio opens the pom editor.
  5. Choose the Dependencies tab from the bottom of the pom editor.
  6. Click Create.
  7. For example, for Hibernate Core, enter:
    Group ID
    org.hibernate
    Artifact ID
    hibernate-core
    Version
    3.3.0.GA
    Scope
    provided

Chapter 4. Task Two: Create the Source Code

Once the project has been created, the source code is added.

Domain Entity

The project needs a domain entity to store information about a User. It is a persistent class, so it also contains JPA mappings.
To create a domain entity:
  1. Create a User.java file in src/main/java/org/jboss/spring/getting/started/domain
  2. Copy the code in Example 4.1, “Domain Entity Definition” into the new file.

Example 4.1. Domain Entity Definition

package org.jboss.spring.getting.started.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="USERS")
public class User {

  @Id
  private Long id;
 
  @Column private String username;

  @Column String firstName;
 
  @Column String lastName;

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getFirstName() {
   return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
   return lastName;
  }

  public void setLastName(String lastName) {
   this.lastName = lastName;
 }
 
}

User DAO Interface

Data access is provided through a JPA-based DAO, which is installed as a Spring bean.
To create the interface for this component:
  1. Create a file called UserDao.java in src/main/java/org/jboss/spring/getting/started/domain
  2. Copy the code in Example 4.2, “Interface for the User DAO” into the new file.

Example 4.2. Interface for the User DAO

package org.jboss.spring.getting.started.domain;

public interface UserDao {
  User getForUsername(String username);
}

UserDAO Implementation

Plain JPA is recommended for the implementation. The class is annotated with @Service, which means that it can be used by Spring to scan for components rather than explicitly defining them in a configuration file.
The entity manager that the implementation uses to run JPA queries will be injected in the corresponding field, and the @Autowired annotation instructs Spring where to do the injection.
The @Transactional annotation is used for demarcating transactions declaratively. This particular setup means that getForUsername() will execute in its own transaction, if a transaction is not yet started. This may change with other configuration options, as Spring supports different transaction propagation modes.
To create a JPA-based DAO implementation:
  1. Create UserDaoImpl.java in src/main/java/org/jboss/spring/getting/started/domain
  2. Copy the code from Example 4.3, “UserDao Implementation” into the new file.

Example 4.3. UserDao Implementation

package org.jboss.spring.getting.started.domain;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserDaoImpl implements UserDao {

    @Autowired
    private EntityManager entityManager;

    @Transactional
    public User getForUsername(String username) {
        Query query = entityManager
                .createQuery("select u from User u where u.username = ?");
        query.setParameter(1, username);
        return (User) query.getSingleResult();
    }

}

Model View Controller Class

The web tier requires a controller, and a web page for displaying results.
To create the UserController class:
  1. Create UserController.java in src/main/java/org/jboss/spring/getting/started/mvc
  2. Copy the code in Example 4.4, “The MVC Controller Class” to the new file.

Example 4.4. The MVC Controller Class

package org.jboss.spring.getting.started.mvc;

import org.jboss.spring.getting.started.domain.User;
import org.jboss.spring.getting.started.domain.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping("say-hello")
public class UserController {

    @Autowired
    private UserDao userDao;

    @RequestMapping(method = RequestMethod.GET)
    public @ModelAttribute("message")
    String getInitialMessage() {
        return "Enter a Valid Name";
    }

    @RequestMapping(method = RequestMethod.POST)
    public @ModelAttribute("message")
    String getGreeting(@RequestParam("username") String username) {
        User user = userDao.getForUsername(username);
        return "Hello, " + user.getFirstName() + " " + user.getLastName() + "!";
    }
}

The @Controller annotation is similar to @Service, but targeted for MVC controller components. It instructs Spring to create a controller bean automatically if it finds the class on the classpath.
The @Autowired annotation is similar to the previous example, instructing Spring to inject a UserDao instance automatically. Specific to this class, however, are the MVC annotations; @RequestMapping, @RequestParam and @ModelAttribute.
The @RequestMapping annotation is added at the class level to map requests that end in 'say-hello' to this controller. The actual URL that will be mapped to it also depends on the rest of the Spring configuration. Spring MVC uses the Front Controller pattern, which means that the requests are dispatched by a servlet, and the mappings in this class are relative to the mapping of the servlet.
The class serves as backing to a web form, and different methods need to execute when the form page is initially requested (GET) and data is posted back (POST). This is why there are two distinct @RequestMapping annotations with which the getInitialMessage() and getForUsername() methods are annotated.
The @ModelAttribute annotation instructs Spring MVC to add the returned value as a request attribute so that it can be used when rendering the view. The @RequestParam instructs Spring to bind the 'username' value submitted by the form to the method parameter.
To finalize the code, a view that renders the form is created. When the page is initially rendered, it will display the warning message returned by getInitialMessage(). After each submission, the page will display a welcome message with the full name of the user.
To create a new JSP page:
  1. Create a new say-hello.jsp file within /src/main/webapp/WEB-INF/views/say-hello.jsp
  2. Copy the code from Example 4.5, “The Web Page That Renders The Results” to the new file.

Example 4.5. The Web Page That Renders The Results

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Hello</title>
</head>
<body>
<form method="post" action="say-hello">Enter username: <input
        type="text" name="username" value="<c:out value="${username}"/>">
    <c:out value="${message}" />
    <p><input type="submit" value="Submit">
</form>

</body>
</html>

4.1. Setting up Persistence

Setting up persistence for the example requires creating a database initialization script and creating a persistence unit.
To create a database initialization script:
  1. Create a file called init-db.sql in src/main/resources.
  2. Copy the code in Example 4.6, “The Database Initialization Script” into the new file.

Example 4.6. The Database Initialization Script

DROP TABLE USERS IF EXISTS CASCADE;
CREATE TABLE USERS (
  ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY, 
  USERNAME VARCHAR(255),
  FIRSTNAME VARCHAR(255),
  LASTNAME VARCHAR(255));
  
INSERT INTO USERS (ID, USERNAME, FIRSTNAME, LASTNAME) VALUES (1, 'jdoe', 'John', 'Doe');
INSERT INTO USERS (ID, USERNAME, FIRSTNAME, LASTNAME) VALUES (2, 'emuster', 'Erika', 'Mustermann');

A persistence unit definition file is also required. To create this file:
  1. Create persistence.xml underneath src/main/resources/META-INF
  2. Copy the code from Example 4.7, “The Persistence Unit Definition File” into the new file.

Example 4.7. The Persistence Unit Definition File

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
   <persistence-unit name="helloPU" transaction-type="JTA">
       <jta-data-source>java:/DefaultDS</jta-data-source>
       <properties>
            <property name="jboss.entity.manager.jndi.name" value="java:/hello/EntityManager"/>
            <property name="hibernate.show_sql" value="true"/>
       </properties>
   </persistence-unit>
</persistence>

Chapter 5. Task Three: Add the Spring Configuration Files

A Spring MVC application uses the Front Controller pattern; this is encountered by other frameworks such as Struts. Requests are directed to a servlet that dispatches them to controller components. It then forwards to a view that renders the response. The Spring configuration consists of two sets of beans which will be bootstrapped in separate application contexts:
business logic beans
which configure and wire together services, wrap them in transactional and AOP proxies;
front-end components
controllers and URL mappings
To configure the web application, copy the code in Example 5.1, “The web.xml Definition” into src/main/webapp/WEB-INF/web.xml.

Example 5.1. The web.xml Definition

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>Getting Started with Spring</display-name>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring-business-context.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<servlet>
		<servlet-name>Spring MVC Servlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring-mvc-context.xml</param-value>
		</init-param>
	</servlet>

	<servlet-mapping>
		<servlet-name>Spring MVC Servlet</servlet-name>
		<url-pattern>/app/*</url-pattern>
	</servlet-mapping>

</web-app>

The ContextLoaderListener will bootstrap an application context containing the business components, while the DispatcherServlet will create an application context using the former as its parent (and thus having access to its bean definitions).
To do this, the Spring Bean Configuration File needs to be added. Follow Procedure 5.1, “Add A Spring Bean Configuration File” to do so.

Procedure 5.1. Add A Spring Bean Configuration File

  1. Select New and then Spring Bean Configuration File
    1. You may have to choose NewOtherSpring
  2. Enter the filename as spring-business-context.xml
  3. Choose the location for the file: src/main/webapp/WEB-INF
  4. Follow the Next option
  5. Select these namespaces:
    • bean
    • context
    • jbdc
    • jee
    • tx
  6. Click Finish
  7. Copy the code in Example 5.2, “ The Spring Business Context” into the new file.

Example 5.2.  The Spring Business Context

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
   xmlns:jee="http://www.springframework.org/schema/jee" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
   xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

   <context:component-scan base-package="org.jboss.spring.getting.started.domain" />

   <jee:jndi-lookup jndi-name="java:/DefaultDS" id="dataSource"
      expected-type="javax.sql.DataSource" />

   <jee:jndi-lookup jndi-name="java:/hello/EntityManager"
      id="entityManager" expected-type="javax.persistence.EntityManager" />

   <tx:jta-transaction-manager />

   <tx:annotation-driven />

   <jdbc:initialize-database data-source="dataSource">
      <jdbc:script location="classpath*:init-db.sql" />
   </jdbc:initialize-database>

</beans>

The instructions given to Spring in the file are as follows:
  1. Spring was instructed to scan the package 'org.jboss.spring.getting.started.domain' for component beans, looking for specific annotations such as @Service, and inject them automatically based on the @Autowired annotation.
    In this case, this will create the bean definition for UserDao, created in Example 4.2, “Interface for the User DAO”.
  2. Beans are created for the data source and the entity manager. This is because a managed data source is being used, as well as a container-managed entity manager.
    The management strategy is set to JTA, and Spring is instructed to apply transactions declaratively, based on the @Transactional annotations found on bean classes.
    Since this is an example, the database needs to be initialized and Spring instructed to run the init-db.sql script at start up.
The front-end components that are used to configure the dispatcher servlet are defined in a file named spring-mvc-context.xml. Follow the instructions in Procedure 5.2, “Create spring-mvc-context.xml” to create a spring-mvc-context.xml file.

Procedure 5.2. Create spring-mvc-context.xml

  1. Select New and then Spring Bean Configuration File
    1. You may have to choose NewOtherSpring
  2. Enter the filename as spring-mvc-context.xml
  3. Choose the location for the file: src/main/webapp/WEB-INF
  4. Follow the Next option
  5. Select these namespaces:
    • bean
    • context
    • mvc
  6. Click Finish
  7. Copy the code from Example 5.3, “Dispatcher Servlet Configuration File” into the new spring-mvc-context.xml.

Example 5.3. Dispatcher Servlet Configuration File

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

   <context:component-scan base-package="org.jboss.spring.getting.started.mvc" />

   <mvc:annotation-driven />

   <bean
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/WEB-INF/views/" />
      <property name="suffix" value=".jsp"></property>
   </bean>
</beans>

Using this context definition, Spring scans for component beans such as the UserController, and uses the mappings defined by the annotations found on controller beans. After a controller is executed, the InternalResourceViewResolver determines a jsp page that DispatcherServlet will forward the request to for rendering the response.

Chapter 6. Task Four: Run the Example

The example can be run from either the command line or from JBoss Developer Studio. Use Procedure 6.1, “Run the Example from the Command Line” for the command line, and Procedure 6.2, “Run from JBoss Developer Studio” for JBoss Developer Studio.

Procedure 6.1. Run the Example from the Command Line

To run the example from the command line, you will need to build the example with Maven and copy it into your JBoss Enterprise Application Platform instance.
  1. Build the example with Maven using mvn clean package within the example directory.
             cd $EXAMPLE_HOME
             mvn clean package
    
  2. Copy the example into your JBoss Enterprise Application Platform instance.
             cp target/getting-started.war $EAP_HOME/jboss-as/server/<profile>/deploy
    
  3. Deploy the example from $EAP_HOME
             sh jboss-as/bin/run.sh
    
  4. After the example has been deployed, it can be accessed at http://localhost:8080/getting-started

Procedure 6.2. Run from JBoss Developer Studio

  1. Right click on the project in the projects list to the left to bring up the dropdown box.
  2. Click Run As, then Run on Server
  3. Choose the JBoss Enterprise Application Platform 5.1 instance.
  4. Click Finish
    If you don't find a JBoss Enterprise Application Platform instance, refer to Section B.2, “Adding a JBoss Enterprise Application Instance”.
  5. After the example has been deployed, it can be accessed at http://localhost:8080/getting-started.

Note

If building your project fails with the error annotations are not supported in -source 1.3, update your pom.xml to the following:
<build>  
    <plugins>  
      <plugin>  
        <artifactId>maven-compiler-plugin</artifactId>  
        <configuration>  
          <source>1.5</source>  
          <target>1.5</target>  
        </configuration>  
      </plugin>  
    </plugins>  
</build>

Part II. Best Practices And Integration Guidelines

Chapter 7. Best Practices

The following are the best practices recommended by Red Hat for using Spring with JBoss Platforms.

7.1. Setting Up Data Access

Spring applications can either deploy their own data access infrastructure, or rely on a managed infrastructure provided by the application server. The recommended practice for JBoss is to use the server-provided infrastructure. Use a managed infrastructure using JTA transaction management.
The following subsections detail the configuration strategy for:
  • datasources;
  • Hibernate SessionFactories;
  • JPA EntityManagers and EntityManagerFactories;
  • transaction management;

7.1.1. Database Access Through Managed Datasources

On JBoss, managed datasources should be used. These are accessible via JNDI, and can be deployed through a configuration file.
The definition for managed datasources is included in a file that ends in -ds.xml (for example, sportsclub-ds.xml).
To use the -ds.xml file, it can be:
  • copied into the deploy directory of the target JBoss application server configuration (for example, default) for deployment at server startup;
  • included in the META-INF directory of the application for deployment with the application.
Example 7.1, “Managed Datasource Configuration” is an example of a datasource in a -ds.xml file.

Example 7.1. Managed Datasource Configuration

<datasources>
   <local-tx-datasource>

      <jndi-name>ExampleDsJndiName</jndi-name>

      <connection-url> example JDBC URL </connection-url>
   ...
   </local-tx-datasource>
</datasources>

The datasource is bound in JNDI at java:/ExampleDsJndiName. For example, if your datasource JNDI name was mydatasource, it would be bound in JNDI at java:/mydatasource.
The datasource is referenced from a Spring ApplicationContext by using the definition in Example 7.2, “Defining a Managed Datasource Spring Bean”. A datasource bean can be injected into any regular Spring bean (for example, a JBDS DAO).

Example 7.2. Defining a Managed Datasource Spring Bean

<jee:jndi-lookup id="dataSource" jndi-name="java:/ExampleDsJndiName" expected-type="javax.sql.DataSource"/>

7.1.2. Hibernate SessionFactory

Applications that need to use Hibernate directly (as opposed to JPA) should use the Hibernate included in the application server. This means that applications do not need to include a Hibernate distribution.
Spring applications can use one of Spring's SessionFactory-instantiating FactoryBeans, and a managed datasource to use Hibernate.

Example 7.3. SessionFactory Bean Definition

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
       ...
</bean>

JTA transaction management and Hibernate-JTA session management integration is recommended. You can use these by setting up the following properties:

Example 7.4. JTA session management setup properties

hibernate.current_session_context_class=jta
hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookup
hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory

Once a SessionFactory has been defined, it can be injected in component classes such as DAOs and used directly as in Example 7.5, “Hibernate-based DAO: a SessionFactory is Injected Directly in the Bean”:

Example 7.5. Hibernate-based DAO: a SessionFactory is Injected Directly in the Bean

public class HibernateAccountDao {
  @Autowired SessionFactory sessionFactory;

  public List<Account> getAllAccounts() {
     return sessionFactory.getCurrentSession().getCriteria(Account.class).list();
  }
  ...
}

A detailed example of using Hibernate-driven data access in Spring-based applications is available in the Sportsclub example application. The example is in your distribution of JBoss Web Framework Kit, and instructions are in the Snowdrop Sportsclub Example User Guide.

7.2. Using JPA

7.2.1. PersistenceUnit Deployed by the Container

Spring applications can retrieve the persistence units deployed by the container by looking them up in JNDI. In order to bind the entity manager or entity manager factory under a well-established name and subsequently look them up, applications can use special Hibernate configuration properties or web.xml.
Use this code in persistence.xml to do so.

Example 7.6. Persistence Unit Definition with JNDI bindings

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
   <persistence-unit name="sportsclubPU">
       <jta-data-source>java:/ExampleDsJndiName</jta-data-source>
       <properties>
            <property name="jboss.entity.manager.jndi.name" value="java:/example/em"/>
            <property name="jboss.entity.manager.factory.jndi.name" value="java:/example/emf"/>
            ...
       </properties>
   </persistence-unit>
</persistence>

Spring applications can use either container-managed entity managers or application-managed entity managers. In this case, they are provided with the corresponding entity manager factories. A container-managed entity manager can be accessed as a Spring Bean, as shown in Example 7.7, “Spring Bean Representing a Container-managed Entity manager”

Example 7.7. Spring Bean Representing a Container-managed Entity manager

<jee:jndi-lookup id="entityManager" jndi-name="java:/example/em"/>

Such an EntityManager can be used directly if injected in component classes such as DAOs.

Example 7.8. Hibernate-based DAO: a SessionFactory is Injected Directly in the Bean

public class HibernateAccountDao {
  @Autowired EntityManager entityManager;

  public List<Account> getAllAccounts() {
     return entityManager.createQuery("SELECT a FROM Account").getResultList();
  }
  ...
}

As an alternative, an EntityManagerFactory can also be used directly, either relying on Spring's ability to perform @PersistenceContext injection with a transactional EntityManager or when the scenario requires an application-managed entityManager. Here is an example of acquiring the entityManagerFactory from JNDI.

Example 7.9. Spring Bean Representing an Entity Manager Factory

<jee:jndi-lookup id="entityManagerFactory" jndi-name="java:/example/emf"/>

In general, for implementing transaction-aware components, it is not typical to access EntityManagerFactories directly (for example a service that delegates to multiple DAOs that have to be enrolled in the same transaction). This is true even if Spring supports injection into fields annotated with @PersistenceContext when an EntityManagerFactory is provided. Rather, components should access the JNDI-bound EntityManager, as it is JTA-synchronized and will be shared with non-Spring components that use JPA as well (for example EJBs).
A comprehensive example of using JPA-driven data access in Spring-based applications can be found in the Sportsclub example application, included in the Web Framework Kit distribution.

7.2.2. PersistenceUnit Created by Spring

When declaring transactions, Spring applications may specify that a transaction is intended to be read-only as in example Example 7.10, “A Spring Method Declaring a Read-Only Transaction”.

Example 7.10. A Spring Method Declaring a Read-Only Transaction

@Transaction(readOnly = true)
public List<Account> getAllAccounts() {
    return entityManager.createQuery("SELECT a FROM Account").getResultList();
}

This means that it can be flushed at the end of the transaction. Spring would normally try to block the persistence context being flushed, but the flag tells Spring to allow it to proceed. This results in a performance increase as the persistence context will be discarded when the transactions ends. Support for this mode is not obligatory in Spring, and applications are not expected to rely on this behaviour at all times.
This behaviour is supported by Spring-defined EntityManagerFactories for certain JPA providers (Hibernate is one of them), but not when the EntityManager or EntityManagerFactory is provided from JNDI. This means that a JTA-integrated LocalContainerEntityManagerFactoryBean should be used for any application that requires support for Read-Only persistence contexts. The following is a bean definition for JBoss:

Example 7.11. A Spring-defined JTA-based Entity Manager Factory

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
    <property name="jpaProperties">
        <props>
             <prop key="hibernate.transaction.manager_lookup_class">
                 org.hibernate.transaction.JBossTransactionManagerLookup
             </prop>
         </props>
    </property>
</bean>
The above definition requires META-INF/persistence.xml to be provided in the deployment. If there is no persistence.xml, Spring will not use a container-deployed persistence unit so it may not be required. If there is no container-deployed persistence unit, another location can be used, as shown in Example 7.12, “Using an Alternative Location for Persistence.xml”.

Example 7.12. Using an Alternative Location for Persistence.xml

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
   <property name="persistenceXmlLocation" value="classpath*:META-INF/persistence-booking.xml"/>
   <!-- other properties (omitted) -->
</bean>

Irrespective of where the persistence.xml file is located or what it is called, the WEB-INF/classes location will not be scanned for persistent entries when the LocalContainerManagedEntityFactoryBean is used. In this case, the list of entities must be provided explicitly through one of the following methods:
  • By enumerating the persistent classes in persistence.xml (or other persistence unit configuration file name);
  • By packaging the entities in a jar file and providing a <jar-file/> configuration entry in persistence.xml;
  • Using a PersistenceUnitPostprocessor;
The first two solutions are based on the standard functionality of JPA. The third solution is Spring-specific and involves implementing a PersistenceUnitPostprocessor class that adds the persistent classes directly to the PersistenceUnitInfo object, as in the following example:

Example 7.13. Example of a PersistenceUnitPostProcessor Implementation That Adds all Classes Annotated with @Entity

package org.springframework.webflow.samples.booking;

import java.io.IOException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;

public class MyPersistenceUnitPostProcessor implements PersistenceUnitPostProcessor
{

   @Autowired
   private ResourcePatternResolver resourceLoader;

   public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo mutablePersistenceUnitInfo)
   {
      try
      {
         Resource[] resources = resourceLoader.getResources("classpath:org/myexample/*.class");
         for (Resource resource : resources)
         {
            CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
            MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(resource);
            if (metadataReader.getAnnotationMetadata().isAnnotated(javax.persistence.Entity.class.getName()))
            {
               mutablePersistenceUnitInfo.addManagedClassName(metadataReader.getClassMetadata().getClassName());
            }
         }
         mutablePersistenceUnitInfo.setExcludeUnlistedClasses(true);
      }
      catch (IOException e)
      {
         throw new RuntimeException(e);
      }
   }
}

A bean of this class can be injected in the LocalContainerEntityManagerFactoryBean as follows:

Example 7.14. Adding the PersistenceUnitPostProcessor to the Context Definition

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!-- other properties -->
  <property name="persistenceUnitPostProcessors">
    <list>
      <bean class="org.springframework.webflow.samples.booking.MyPersistenceUnitPostProcessor"/>
    </list>
  </property>
</bean>

7.2.3. @PersistenceContext and @PersistenceUnit Injection

Spring injects @PersistenceContext into Spring components on its own. In order to do so, applications need to be have access to an EntityManagerFactory bean (either created by Spring or looked up in JNDI).
The presence of @PersistenceContext or @PersistenceUnit annotations in Spring may cause deployment errors when the persistence.xml has been renamed. The persistence.xml may be renamed in order to use a Spring-based EntityManagerFactory). The errors occurr because in a Java EE 5 environment, the @PersistenceContext and @PersistenceUnit annotations are used for supporting the container-driver injection of container-managed persistence contexts and persistence units, respectively. During deployment, JBoss Enterprise Application Platform scans the deployment classes and validates that if such annoations are found, the corresponding managed persistence units exist as well. This is not the case if the persistence.xml file has been renamed.
This can be resolved either by disabling the scanning of deployment classes, or by using the @Autowire injection.
In the case of Spring-based deployments, the injection of components and resources is done by Spring and not by JBoss, so in most cases it is not necessary for JBoss to perform the scanning at all. For web applications conforming to the Servlet 2.5 specification this can be set up through the metadata-complete attribute (applications that use the Servlet 2.4 standard do not exhibit this problem at all, since annotation-based injection is not supported by the container).

Example 7.15. The Metadata-complete Flag Can Be Used to Disable Class Scanning by JBoss

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         metadata-complete="true">
An alternative is to use @Autowired instead of @PersistenceUnit/@PersistenceContext. In the case of @PersistenceUnit/EntityManagerFactory injection, it is just a matter of replacing the annotation, but @PersistenceContext requires an extra step.
If you are using a container-deployed EntityManagerFactory, you can register bind the EntityManager in JNDI, as explained in the previous subsection, and use a JNDI lookup bean to retrieve it.
If you are using a Spring-deployed EntityManagerFactory, you can autowire a transaction-aware EntityManager by adding a SharedEntityManagerBean definition as in the following example.

Example 7.16. Using a SharedEntityManager Bean to Create an Injectable Transaction-aware EntityManager

<bean id="entityManagerWrapper" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
   <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

7.3. Messaging (JMS) Integration

Spring applications have two distinct mechanisms of integrating with JMS. One is by using the JmsTemplate which simplifies the usage of the JMS API for both sending and receiving messages, and the other is by implementing message-driven POJOs.
The best practice in JBoss is to use the JmsTemplate for sending messages, but not for receiving them.
Spring applications can implement message-driven POJOs by wiring MessageListener beans (or POJOs via a MessageListenerAdapter) into a MessageListenerContainer.

Example 7.17. A message-driven POJO is a simple Java class with a single-argument method

public class MessageDrivenPojo
{
  @Autowire PaymentProcessor paymentProcessor;

  public void pojoHandlerMethod(PaymentNotification paymentNotification)
  {
    paymentProcessor.processPayment(paymentNotification.getAccountNumber(), paymentNotification.getAmount());
  }
}

Spring provides two different types of MessageListenerContainers; 'native' JMS, and JCA-based. The Enterprise Application Platform uses the JCA MessageListenerContainer due to better integration with the application server for server message and delivery session, connection, and message consumer management. In order to minimize the amount of proprietary code, Snowdrop's namespace support for JMS/JCA integration can be used .

Example 7.18. Using the JCA Message Listener Containers and Namespace Support in JBoss

 <jms:jca-listener-container resource-adapter="resourceAdapter" acknowledge="auto"
                                activation-spec-factory="activationSpecFactory">
        <jms:listener destination="/someDestination" ref="messageDrivenPojo"
                      method="pojoHandlerMethod"/>
    </jms:jca-listener-container>


    <jboss:activation-spec-factory id="activationSpecFactory" subscriptionName="jca-example" useDLQ="false"/>

    <jboss:resource-adapter id="resourceAdapter"/>

    <bean id="messageDrivenPojo" class="example.MessageDrivenPojo"/>

When a message arrives, the container will invoke the messageDrivenPojo bean. The message will then be converted to the argument type of the pojoHandlerMethod inside that bean. Any regular bean can be a message-driven POJO; the only restriction is that the handling method must have a single argument. Spring will take care of converting message content to the expected argument type. For a JCA-based container, the invocation will be automatically enrolled in a JTA transaction.

7.4. Transaction Management

Spring provides a declarative transaction model including transaction propagation semantics, so that applications can declare transaction boundaries around specific methods either through annotation or via XML. An example using annotations can be found in Example 7.10, “A Spring Method Declaring a Read-Only Transaction” and more extensively in the Sportsclub example application. It is important to note that the model is the same regardless of whether the transactions being used are local transactions or JTA transactions. Spring will wrap components in a transactional proxy which will delegate to a transaction manager; which is declared separately as a Spring bean. Through its PlatformTransactionManager abstraction, Spring lets developers to choose between using resource-local transactions or delegating to the transaction manager provided by the application server.
Transaction support in JBoss Enterprise Application Platform is provided by JBoss Transaction Service, a highly configurable transaction manager. To use the JBoss Transaction Service in a Spring application, use the standard Spring JTA transaction manager definition.

Example 7.19. JTA Transaction Manager Definition in Spring

<tx:jta-transaction-manager id="transactionManager"/>

The use of this transaction manager allows Spring to create JTA transactions (for example, through Spring declarative transaction management), or to enroll in existing transactions, if any. It requires the use of managed datasources, JTA-integrated session factories or container-deployed persistence units, and ensures that the underlying database connections, sessions, and persistence contexts are managed transparently and shared with other components.

JTA and Messaging Integration

As described in Section 7.3, “Messaging (JMS) Integration”, the recommended integration method for receiving JMS messages is through a JCA-endpoint based MessageListenerContainer. The processing of a message (that is, during the call to the message handling method) is wrapped in a JTA transaction. As a result, any other JTA-aware resources (datasources, entity manager factories, session factories, JMS sessions) will participate in the same transaction.
Spring's JMS utility classes such as JmsTemplate and even the DefaultMessageListenerContainer support injection with a Spring transaction manager abstraction. By injecting them with the JTA-based implementation defined as previously described, you can ensure that the JMS-based operations are enrolled in JTA transactions as well.

7.5. EJB Integration

Although there is overlap between EJB and Spring, mixing the two component models together is common. It consists of having components of one type delegating functionality to components of the other type. The best practice is to provide the delegate components via injection, which can happen in any direction (Spring to EJB and EJB to Spring).

7.5.1. Injecting Spring Beans Into EJBs

For JBoss Enterprise Application Platform 5 there are two major options of injecting Spring beans into EJBs:
  • Using Spring's native support for EJB integration
  • Using Snowdrop

Using Spring's Native Support for EJB Integration

Spring supports injection into EJBs through its SpringBeanAutowiringInterceptor, which honors the @Autowired annotation.

Example 7.20. Injecting a Spring Bean into EJBs Using Spring's Native Support

@Stateless
@Interceptors(SpringBeanAutowiringInterceptor.class)
public class InjectedEjbImpl implements InjectedEjb {

    @Autowired
    private SpringBean springBean;
  
}

The injected Spring beans are retrieved from an ApplicationContext located using a ContextSingletonBeanFactoryLocator, which uses a two-step method for locating contexts. It relies on the existence of one or more files named beanRefContext.xml on the classpath (in other words, it performs a 'classpath*:beanRefContext.xml' lookup), which contains a single application context definition. Example 7.21, “Simple beanRefContext.xml File Used by a ContextSingletonBeanFactoryLocator and the Corresponding simpleContext.xml” contains the definition of such a file.

Example 7.21. Simple beanRefContext.xml File Used by a ContextSingletonBeanFactoryLocator and the Corresponding simpleContext.xml

<beans>
    <bean class="org.springframework.context.support.ClassPathXmlApplicationContext">
        <constructor-arg value="classpath*:simpleContext.xml" />
    </bean>
</beans
<beans>
  <bean id="springBean" class="example.SpringBean"/>
</beans>

Using Snowdrop

Snowdrop is a package of JBoss-specific extensions to Spring, which is included with JBoss Web Framework Kit. This section provides an overview of how to inject Spring beans into EJBs using Snowdrop support. For more details and a more elaborate example, please consult the Snowdrop User Guide and the Sportsclub Example.
Snowdrop supports the bootstrapping of Spring application contexts through its JBoss-specific Spring deployer. This identifies Spring bean configuration files (regular application context XML definitions) which are deployed in the META-INF directory of a deployable module (EAR, WAR, or EJB-JAR) and match a specific pattern (by default, *-spring.xml). It will bootstrap ApplicationContexts, which are further registered in JNDI under a name which can be configured from within the context definition.

Example 7.22. Spring Beans Configuration File (example-spring.xml)

<beans>
  <description>BeanFactory=(MyApp)</description>
  <bean id="springBean" class="example.SpringBean"/>
</beans>

Example 7.22, “Spring Beans Configuration File (example-spring.xml)” contains a minimal Spring bean definition file. The Spring deployer will bootstrap a context that contains a 'springBean' bean and will register it in JNDI under the 'MyApp' name.
Beans defined in such contexts can be injected into EJBs, by using the Snowdrop-specific SpringLifecycleInterceptor and @Spring annotation.

Example 7.23. Injecting a Spring Bean into an EJB Using Snowdrop

@Stateless
@Interceptors(SpringLifecycleInterceptor.class)
public class InjectedEjbImpl implements InjectedEjb
{
 @Spring(bean = "springBean", jndiName = "MyApp")
 private SpringBean springBean;

 /* rest of the class definition omitted */
}

7.5.2. Accessing EJBs from Spring Beans

Injecting stateless EJBs in Spring components is also possible. There are two ways this can be done:
  • EJB reference bean definitions
  • using the @EJB annotation in Spring
EJB references can be defined as Spring beans using the <jee:local-slsb>/<jee:remote-slsb> elements, as in Example 7.24, “Defining an EJB Reference as a Spring Bean”

Example 7.24. Defining an EJB Reference as a Spring Bean

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:jee="http://www.springframework.org/schema/jee"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">

  <jee:local-slsb id="ejbReference" jndi-name="ejb/exampleEjb"
      business-interface="example.ExampleEjb/>

  <bean id="consumerBean" class="example.ConsumerBean"/

</beans>
The EJB references are regular Spring beans and can be injected as any other Spring beans would.

Example 7.25. Injecting an EJB Reference Defined as a Spring Bean

public class ConsumerBean {

    @Autowire ExampleEjb exampleEJB;

}
Spring also supports injection directly with EJB references, as in the following example:

Example 7.26. Injecting an EJB Using Annotations

public class ConsumerBean {

    @EJB(mappedName="ejb/exampleEJB")
    ExampleEjb exampleEJB;

}
Unlike @EJB references in EJBs, which may not specify a name or mappedName, and relies upon the container to resolve the reference automatically, @EJB references in Spring beans must specify the JNDI location where the EJB is expected to be found.

Part III. Migration

Chapter 8. Migrating applications to JBoss EAP and EWP

This chapter explores how Spring applications that have been originally developed for servlet containers can be migrated to take advantage of the JBoss middleware service support and infrastructure. Sample applications provided by the Spring frameworks will be used to do so.

8.1. General Migration Mechanics

Migrating applications from a servlet container to one of the enterprise platforms is a process that addresses two distinct concerns:
  • ensuring that the applications are compatible with the requirements of the Java EE 5 standard;
  • enabling integration with the middleware services provided by the container;
  • avoiding the inclusion of libraries that are already provided by the application server.
Except for rare situations, migrating applications does not involve changes to the Java code, or the Spring bean configuration definitions that define the business logic of the application (bean wiring, aspect definitions, and controllers). The definitions that relate to the infrastructure are:
  • session factories
  • datasources
  • entity managers

Avoiding the Inclusion of Server-Provided Dependencies

The JBoss Enterprise platforms already provide a number of dependencies that are required by applications. This is unlike servlet containers, where applications need to package a significant number of libraries in order to provide access to certain Java EE 5 technologies. One of the things to be considered in the migration process is changing the deployable build by removing the libraries which are already provided by the application server. It is not just an improvement which reduces the size of the final build, but also a requirement, since the inclusion of those libraries will result in classloading errors.
Some examples of libraries provided by JBoss Enterprise Application Platform which do not need to be included in the application are:
  • The Java EE 5 APIs (JPA, JSTL, JMS and many others);
  • Hibernate (including Hibernate as a JPA provider)
  • JSF
The components above may be required as compile-time dependencies, so they need to be included in the project, but not packaged in the final build. In Maven builds, this can be achieved by setting the scope to 'provided' and in JBoss Developer Studio by unchecking the Exported flag for the dependency. Other build systems have their own respective mechanisms of achieving the same goal.
However, components and frameworks that are not part of the Java EE 5 implementation but are certified for use with JBoss Enterprise Application Platform 5 need to be included in your application. These components are:
  • Spring Framework (consult the Spring Installation Guide for more details)
  • Snowdrop
  • Facelets
  • RichFaces

Migrating Datasource Definitions

Most servlet containers support the use of JNDI-bound resources, and binding Datasources in JNDI allows for managing connectivity parameters such as URLs, credentials, and pool sizes independently from the application code. However, Spring applications often rely on independent connection pool bean definitions, such as the ones used by commons-dbcp or c3po (see Example 8.1, “Example commons-dbcp DataSource definition in a servlet container”).

Example 8.1. Example commons-dbcp DataSource definition in a servlet container

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="org.postgresql.Driver" />
  <property name="url" value="jdbc:postgresql://exampleHost/exampleDatabase" />
  <property name="username" value="user" />
  <property name="password" value="password" />
</bean>
JBoss provides an efficient way of deploying and maintaining managed datasources (see Section 7.1.1, “Database Access Through Managed Datasources” for more details and the JBoss Enterprise Application Platform Administration and Configuration Guide for how to deploy them,) which are JNDI-accessible. In order to replace the above defined datasource with a managed, JNDI-accessible datasource, replace the bean definition with a JNDI object reference as in Example 8.2, “Using a JBoss managed datasource in Spring”.

Example 8.2. Using a JBoss managed datasource in Spring

<jee:jndi-lookup id="dataSource" jndi-name="java:/ExampleDsJndiName" expected-type="javax.sql.DataSource"/>
Preserving the bean id is important for when the bean is injected by name. Indicating the expected type specifically is important for @Autowired scenarios.

Migrating Hibernate SessionFactories to JTA

Users running applications on the JBoss Enterprise Application Platform are encouraged to use JTA for transaction management. In such cases, the infrastructure changes consist of altering the session factory definition to allow for JTA-backed session context and replacing the local Spring-based transaction manager with a HibernateTransactionManager.
Listing Example 8.3, “SessionFactory and transaction manager definitions in a servlet environment” contains typical bean definitions for the SessionFactory and the transaction manager when used in a servlet container with local Hibernate-based transactions enabled.

Example 8.3. SessionFactory and transaction manager definitions in a servlet environment

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingLocations" value="classpath:**/*.hbm.xml"/>
    <property name="hibernateProperties">
        <value>
              hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
              hibernate.show_sql=true
        </value>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>
These definitions can be migrated to use JTA (the datasource is assumed to be a managed datasource, as shown previously).

Example 8.4. JTA-based SessionFactory and transaction manager

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mappingLocations" value="classpath:**/*.hbm.xml"/>
        <property name="hibernateProperties">
           <value>
              hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
              hibernate.show_sql=true
              hibernate.current_session_context_class=jta
              hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookup
              hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory
           </value>
        </property>
    </bean>

<tx:jta-transaction-manager id="transactionManager"/>

Note

The definitions of the 'sessionFactory' bean is virtually unchanged; the only difference is the addition of the properties required for setting up the JTA-based context management and the transaction manager change.

Migrating JPA-based Applications

The most important aspect in the case of JPA is that fully-fledged Java EE 5 environments have certain restrictions regarding what is deployable by the container and what is not. Specifically, a persistence unit definition contained in a META-INF/persistence.xml file will be automatically deployed by the container, cannot declare a RESOURCE_LOCAL transaction type, and must include a JTA datasource reference.
However, it is quite common for applications that are deployed in a servlet container to use RESOURCE_LOCAL transactions as shown in example Example 8.5, “A sample persistence unit definition for a servlet-container based application”. It may also not specify any transaction type (which is equivalent to setting a JTA transaction type, but is ignored when the persistence unit is initialized by Spring and a resource-local model will be used instead). It is also atypical for servlet-container based applications to use JTA datasources, as seen in the same example Example 8.5, “A sample persistence unit definition for a servlet-container based application”.

Example 8.5. A sample persistence unit definition for a servlet-container based application

<persistence-unit name="examplePU" transaction-type="RESOURCE_LOCAL">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
         <property name="hibernate.show_sql" value="true"/>
         <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/>
      </properties>
</persistence-unit>

A servlet container will not deploy a persistence unit automatically, as a Java EE 5 application server would. Therefore Spring applications using JPA will rely on Spring to create the persistence unit by using one of its JPA support factory beans. Furthermore, while in a Java EE 5 application, server enrollment in JTA transactions is a requirement, Spring applications running outside Java EE have to set up a resource-local transaction manager as described in example Example 8.6, “JPA EntityManagerFactory and transaction setup in a servlet-container based application”.

Example 8.6. JPA EntityManagerFactory and transaction setup in a servlet-container based application

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
      p:dataSource-ref="dataSource">    
    <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
        p:database="${jpa.database}" p:showSql="${jpa.showSql}"/>
    </property>
</bean>


<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
   p:entityManagerFactory-ref="entityManagerFactory"/>

This persistence unit definition, as laid out above, is not compatible with the requirements of Java EE 5 for application containers and will lead to the a deployment failure if found in the typical META-INF/persistence.xml location.
To solve this problem and turn it into an application that can be deployed in JBoss:
  • rename the persistence unit definition file;
  • leave persistence-unit deployment to JBoss and using JNDI lookup for retrieving entity managers and entity manager factories.
When renaming the persistence unit, the alternate location can be provided as a property to the LocalContainerEntityManagerFactoryBean as described in example Example 8.7, “LocalContainerEntityManagerFactoryBean with alternate persistence.xml location”. For details about using the LocalContainerEntityManagerFactoryBean in JBoss and its implications, please refer to the previous chapter.

Example 8.7. LocalContainerEntityManagerFactoryBean with alternate persistence.xml location

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
   <property name="persistenceXmlLocation" value="classpath*:META-INF/jpa-persistence.xml"/>
   <!-- other properties (ommitted) -->
</bean>
A more effective approach is converting the persistence.xml definition to a JTA-based model and using JNDI lookup for retrieving the entity manager. For this, convert the persistence unit definition as in the following example (please note that it is not necessary to provide values for both 'jboss.entity.manager.jndi.name' and 'jboss.entity.manager.factory.jndi.name', but one must be specified)

Example 8.8. Changing the persistence.xml definition to be Java EE 5-compatible

<persistence-unit name="examplePU">
      <jta-data-source>java:/ExampleDsJndiName</jta-data-source>
      <properties>
         <property name="hibernate.show_sql" value="true"/>
         <property name="jboss.entity.manager.jndi.name" value="java:/example/EntityManager"/>
         <property name="jboss.entity.manager.factory.jndi.name" value="java:/example/EntityManagerFactory"/>
      </properties>
</persistence-unit>
The EntityManagerFactory or a JTA-synchronized EntityManager can be retrieved from JNDI as follows:

Example 8.9. EntityManager retrieved by JNDI lookup and JTA transaction manager (works with @Autowired)

<jee:jndi-lookup id="entityManager" jndi-name="java:/example/EntityManager" expected-type="javax.persistence.EntityManager"/>


<tx:jta-transaction-manager/>
If the original application relied on Spring to inject the EntityManager using the @PersistenceContext annotation into services and DAOs, using the EntityManager will require changing the annotation to @Autowired (as the bean is an EntityManager). In such cases, it may be better to look up for the EntityManagerFactory instead, and leave Spring to create the EntityManager.
A particular concern when migrating JPA-based application is the choice of a JPA provider. While servlet-container-based applications have to include a JPA implementation and specify the nature of the provider explicitly, JBoss Enterprise Application Platform uses Hibernate as a JPA provider.

Example 8.10. EntityManagerFactory retrieved by JNDI lookup and JTA transaction manager (works with @PersistenceContext)

<jee:jndi-lookup id="entityManager" jndi-name="java:/example/EntityManager" expected-type="javax.persistence.EntityManager"/>


<tx:jta-transaction-manager/>
If the original application relied on Spring to inject the EntityManager using the @PersistenceContext annotation into services and DAOs, using the EntityManager will require changing the annotation to @Autowired (as the bean is an EntityManager). In such cases, it may be better to look up for the EntityManagerFactory instead, and leave Spring to create the EntityManager.
A particular concern when migrating JPA-based application is the choice of a JPA provider. While servlet-container-based applications have to include a JPA implementation and specify the nature of the provider explicitly, JBoss Enterprise Application Platform uses Hibernate as the unique JPA provider. In such cases, using an application-server deployed persistence unit simplifies the process.



8.2. Spring's PetClinic

Our first migration use case is based on the Spring PetClinic sample application, which can be checked out from https://src.springframework.org/svn/spring-samples/petclinic/trunk/.
The example provides a number of alternative data access implementations that can be used alternatively by changing the web.xml file. This shows the migration strategies in each case, noting that only one of these strategies is used at a time.

Preliminary Changes

Before starting the actual migration process, a few adjustments to the POM file will be made, in order to retrieve dependencies from Maven Central or the JBoss repository. The changes consist of renaming artifacts and do not affect the structure of the project, in the sense that the final build will be equivalent with the original in terms of included dependencies, except that it will built with components retrieved from Maven Central and the JBoss repository. The changed POM can be found in Appendix A, and its content can be copied over to the original pom.xml.

Adjusting Dependencies

One of the first things that need focus is adjusting dependency scopes. They will need to change as follows:
  • commons-dbcp:commons-dbcp, commons-pool:commons:pool and org.hsqldb:hsqldb become test-scoped dependencies. A pooled datasource will be retrieved from JNDI at runtime, so they are needed only for running tests;
  • javax.persistence:persistence-api, org.hibernate:hibernate-core, org.hibernate:hibernate-entitymanager, org.hibernate:hibernate-annotations become provided-scope dependencies. JBoss Enterprise platforms include a JPA implementation, so there is no need for the application to include these libraries in the WAR, but they are needed for compiling the application. They are also needed for compiling and running unit tests;
  • javax.servlet.jsp.jstl:jstl-api needs to be set as a provided dependency again, since it is available in JBoss;
  • toplink.essentials:toplink-essentials and org.apache.openjpa:openjpa will be removed from the dependency set, since Hibernate will be used exclusively as a JPA provider.
At this point, the set of dependencies of the application is compatible with JBoss.

Renaming files

A slightly unexpected set of changes is caused by the naming of the application context definition files. In particular, the file applicationContext-hibernate.xml found in /src/main/webapp/WEB-INF/spring may cause problems when deployed in JBoss Enterprise Applicaton Platform, since the Hibernate deployer will try to process it. This can result in a deployment failure. To avoid this, rename the four applicationContext-*.xml files from /src/main/webapp/WEB-INF/spring to:
  • applicationContextDataSource.xml
  • applicationContextHibernate.xml
  • applicationContextJdbc.xml
  • applicationContextJpa.xm
Since they are referred from web.xml, that file has to change as well.

Switching to a JTA and Managed Persistence Context Model

The persistence unit definition must be made deployable by JBoss. In order to do so,
  1. Copy jpa-persistence.xml to /src/test/resources/META-INF
  2. Rename it to persistence.xml
  3. Change its contents to make it Java EE 5-compatible as described in the previous sections.
  4. Result

    Example 8.11. Migrated persistence.xml definition

    <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="PetClinic" transaction-type="JTA">
    
      <jta-data-source>java:/DefaultDS</jta-data-source>
     <!-- Explicitly define mapping file path, else Hibernate won't find the default -->
      <mapping-file>META-INF/orm.xml</mapping-file>
    
      <!-- Prevent annotation scanning. In this app we are purely driven by orm.xml -->
      <exclude-unlisted-classes>true</exclude-unlisted-classes>
    
      <properties>
         <property name="jboss.entity.manager.factory.jndi.name" value="java:/petclinic/emf"/>            
      </properties>
     </persistence-unit>
    </persistence>

For this migration, the default datasource provided by JBoss will be used. You are able to replace it with a datasource JNDI name that is specific to your environment. The deployer will be instructed to bind the EntityManagerFactory in JNDI under a specific name.
Since a Java EE datasource, this needs to be reflected in the configuration file. Go to applicationContextDataSource.xml, comment the DBCP-based datasource definition, and uncomment the one using the <jee:jndi-lookup/> element. Now the datasource will be provided by a JNDI lookup.
For simple JDBC access, the transaction model needs to be switched to JTA. The applicationContextJdbc.xml file must be changed by replacing the DataSourceTransactionManager bean definition with the one using the JtaTransactionManager (or the <tx:jta-transaction-manager/> element).
For Hibernate access, the definition of the Hibernate SessionFactory must be adjusted in order to make it JTA-aware. The applicationContextHibernate.xml is modified next by adding the JTA configuration properties to the SessionFactory definition, removing the HibernateTransactionManager and switching transaction management to JTA by uncommenting the JtaTransactionManager bean definition.

Example 8.12. Migrated SessionFactory and transaction manager /definition

	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
			p:dataSource-ref="dataSource" p:mappingResources="petclinic.hbm.xml">
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
				<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
				<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
                <prop key="hibernate.current_session_context_class">jta</prop>
                <prop key="transaction.manager_lookup_class"
                >org.hibernate.transaction.JBossTransactionManagerLookup</prop>
                <prop key="hibernate.transaction.factory_class">
                org.hibernate.transaction.JTATransactionFactory</prop>
			</props>
		</property>
		<property name="eventListeners">
			<map>
				<entry key="merge">
					<bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
				</entry>
			</map>
		</property>
	</bean>


	<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>


The JPA configuration also has to be changed. In order to do so, remove the EntityManagerFactory bean definition from applicationContextJpa and replace it with an EntityManagerFactory lookup, as well as changing transaction management to JTA.

Example 8.13. Migrated JPA EntityManagerFactory definition and

    <jee:jndi-lookup id="entityManagerFactory" jndi-name="java:/petclinic/emf" expected-type="javax.persistence.EntityManagerFactory"/>

    <tx:jta-transaction-manager/>

Adjusting Unit Tests

The most important change to the unit tests is caused by switching our JPA from Spring-managed to container-managed. As such, unit tests, which run outside a container, will still need to have access to a EntityManagerFactory. Use the original jpa-persistence.xml file, which was copied underneath /src/test/resources/META-INF while doing the migration.
You also need to make sure that OpenJpaEntityManagerClinicTests and EntityManagerClinicTests do not run during the build (since OpenJpa nor Toplink are being used). Do this by annotating them with @Ignore.
This concludes the migration of Spring's Petclinic application to JBoss. You can build the project using maven and copy the resulting war (target/petclinic.war) to $JBOSS_HOME/server/<profile>/deploy, or you can import the Maven project in JBoss Developer Studio (if you have the m2eclipse plugin installed).

8.3. Spring Travel

The case of Spring Travel (https://src.springframework.org/svn/spring-samples/travel/) is very similar to Petclinic, in the sense that it will need to follow the series of steps for migration:
  • Before the migration; adapting the POM to use the JBoss repositories or Maven central (one particular concern is that the example is using a version of Hibernate
  • Setting the Proper Scopes for Dependencies;
  • Switching datasources, transaction managers, persistence unit and entity manager factories to JTA.

The special Case of Flow-scoped Persistence

While in general using a JNDI-provided EntityMangerFactory or EntityManager is a better solution, there are cases when using a JTA-based LocalContainerEntityManagerFactory may be necessary. As shown in the previous chapter, this is necessary when the application relies on the support for the read-only transactions in Spring. In the particular case of Spring Webflow, this is necessary when the application uses a flow-scoped persistence context. In such cases, the persistence context is flushed only when the flow ends so any other transactional operations must complete without saving the persistence context (which is what the read-only flag is intended to do).
Since the project will not use a JNDI-based persistence unit anymore, its deployment can be suppressed by renaming the persistence.xml file to jpa-persistence.xml and disabling class scanning by setting the metadata-complete flag in web.xml (see previous chapter for details).
The EntityManagerFactory bean definition found in data.xml needs to change as follows:

Example 8.14. Changing the EntityManagerFactory bean definition for Spring Travels to support JTA

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
    <property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"/>
    <property name="jpaProperties">
        <props>
             <prop key="hibernate.transaction.manager_lookup_class">
                 org.hibernate.transaction.JBossTransactionManagerLookup
             </prop>
         </props>
    </property>
</bean>

Content of pom.xml files for the examples

A.1. Content of pom.xml File for the Getting Started Example

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.jboss.snowdrop.getting.started</groupId>
   <artifactId>getting-started</artifactId>
   <packaging>war</packaging>
   <version>1.0</version>
   <name>getting-started Maven Webapp</name>
   <url>http://maven.apache.org</url>
   <dependencies>
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.7</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.hibernate</groupId>
         <artifactId>hibernate-core</artifactId>
         <version>3.3.0.GA</version>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>org.hibernate</groupId>
         <artifactId>hibernate-entitymanager</artifactId>
         <version>3.4.0.GA</version>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>taglibs</groupId>
         <artifactId>standard</artifactId>
         <version>1.1.2</version>
      </dependency>
      <dependency>
         <groupId>commons-logging</groupId>
         <artifactId>commons-logging</artifactId>
         <version>1.1.1</version>
      </dependency>
      <dependency>
         <groupId>aopalliance</groupId>
         <artifactId>aopalliance</artifactId>
         <version>1.0</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-asm</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-aop</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-expression</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-beans</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context-support</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-tx</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-core</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-jdbc</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-web</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-orm</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-webmvc</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
   </dependencies>
   <build>
      <finalName>getting-started</finalName>
   </build>
</project>

A.2. Modified Starting pom.xml File for Pet Clinic Migration

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.springframework.samples</groupId>
    <artifactId>petclinic</artifactId>
    <name>petclinic</name>
    <packaging>war</packaging>
    <version>1.0.0-SNAPSHOT</version>
    <properties>
        <spring.version>3.0.0.RELEASE</spring.version>
        <slf4j.version>1.5.6</slf4j.version>
    </properties>
    <dependencies>

        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
            <exclusions>
                <!-- Exclude Commons Logging in favor of SLF4j -->
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- AspectJ -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.8</version>
        </dependency>

        <!-- Logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jcl</artifactId>
            <version>${slf4j.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.15</version>
            <scope>runtime</scope>
            <exclusions>
                <exclusion>
                    <groupId>com.sun.jdmk</groupId>
                    <artifactId>jmxtools</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jmx</groupId>
                    <artifactId>jmxri</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- DataSource -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.2.2</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>commons-pool</groupId>
            <artifactId>commons-pool</artifactId>
            <version>1.5.3</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <version>1.8.0.10</version>
            <scope>runtime</scope>
        </dependency>
        <!-- MySQL JDBC Connector -->
        <!--
              <dependency> <groupId>com.mysql.jdbc</groupId>
              <artifactId>com.springsource.com.mysql.jdbc</artifactId>
              <version>5.1.6</version> </dependency>
          -->

        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>3.3.1.GA</version>
        </dependency>

        <!-- JPA -->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
        </dependency>

        <dependency>
            <groupId>toplink.essentials</groupId>
            <artifactId>toplink-essentials</artifactId>
            <version>2.0-58g</version>
        </dependency>
        <!-- Hibernate JPA Provider -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>3.4.0.GA</version>
            <exclusions>
                <!-- Exclude Commons Logging in favor of SLF4j -->
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-annotations</artifactId>
            <version>3.4.0.GA</version>
            <exclusions>
                <!-- Exclude Commons Logging in favor of SLF4j -->
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- Open JPA Provider -->
        <dependency>
            <groupId>org.apache.openjpa</groupId>
            <artifactId>openjpa</artifactId>
            <version>1.1.0</version>
            <exclusions>
                <!-- Exclude Commons Logging in favor of SLF4j -->
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl-api</artifactId>
            <version>1.2</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.el</groupId>
                    <artifactId>el-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>

        <!-- Rome RSS -->
        <dependency>
            <groupId>rome</groupId>
            <artifactId>rome</artifactId>
            <version>0.9</version>
        </dependency>
        <dependency>
            <groupId>org.jdom</groupId>
            <artifactId>jdom</artifactId>
            <version>1.1</version>
            <scope>runtime</scope>
        </dependency>

        <!-- Test dependencies -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.transaction</groupId>
            <artifactId>transaction-api</artifactId>
            <version>1.1</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <repositories>
        <repository>
            <id>jboss-public-repository-group</id>
            <name>JBoss Public Maven Repository Group</name>
            <url>https://repository.jboss.org/nexus/content/groups/public/</url>
            <layout>default</layout>
            <releases>
                <enabled>true</enabled>
                <updatePolicy>never</updatePolicy>
            </releases>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>never</updatePolicy>
            </snapshots>
        </repository>
    </repositories>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <verbose>true</verbose>
                    <source>1.5</source>
                    <target>1.5</target>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <includes>
                        <include>**/*Tests.java</include>
                    </includes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <warName>petclinic</warName>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>install</id>
                        <phase>install</phase>
                        <goals>
                            <goal>sources</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Setting up JBDS

B.1. Setting up Maven for m2eclipse

The m2eclipse plugin is bundled with a SNAPSHOT version of Maven. You can configure it to use a specific Maven version. In order to do so:
  1. Go to Preferences
  2. Select Maven-Installations
  3. Click Add
When you have done this, you will be prompted to select the directory which contains the Maven distribution that you intend to use. After doing so, a new Maven version is added to the list. Make sure that the checkbox besides it is selected (which means that this particular version of Maven will be used by default by m2eclipse).

B.2. Adding a JBoss Enterprise Application Instance

A regular installation of JBoss Developer Studio will set up one or more JBoss Enterprise Application Platform instances. However, it is possible to add more instances after the installation if that is necessary. See the JBoss Developer Studio Getting Started Guide for more information.

Revision History

Revision History
Revision 1.2.0-21.4002013-10-31Rüdiger Landmann
Rebuild with publican 4.0.0
Revision 1.2.0-212012-07-18Anthony Towns
Rebuild for Publican 3.0
Revision 2-0Wed Jun 8 2011Rebecca Newton
Pushing live for the WFK 1.2 release.
Revision 1-0Thu May 12 2011Rebecca Newton
First push to stop of rewritten book.

Index

F

feedback
contact information for this manual, Give us Feedback

H

help
getting help, Do You Need Help?