Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: WW-3020: Invalid links in Struts 2 + Spring 2 + JPA + AJAX Tutorial

...

Table of Contents
minLevel2
outlinetrue
stylenone

Prerequisites

Tomcat

Install Tomcat before going forward. See Tomcat's installation guide if you have any problem installing it.

MySql

Install and configure MySql. Create a database named "quickstart" and run the script below to create the "Person" table. Later, on applicationContext.xml, we'll use 'root' as the user name and password for the database, remember to replace those values with the right ones for your database.

Code Block
SQL
SQL
CREATE TABLE 'quickstart'.'Person' (
  'id' INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  'firstName' VARCHAR(45) NOT NULL,
  'lastName' VARCHAR(45) NOT NULL,
  PRIMARY KEY('id')
)
ENGINE = InnoDB;

Get the code

Show me the code

You can just download the zipped Eclipse project, add the required dependencies to the lib folder under the /WebContent/WEB-INF/lib folder (relative to project's root folder) and import it into Eclipse.

The maven way

To run the project this way you will need maven installed.

  1. Download the zipped project
  2. Download jta jar from here.
    • Note that the Download Manager may save the file to your root drive, and it may give the file a .ZIP extension. You must rename the file to jta-1.1-classes.jar.
    • If a later version is available, update the version references in the next step.
  3. Install the jta jar file running:
    Code Block
    $ mvn install:install-file -DgroupId=javax.transaction -DartifactId=jta -Dversion=1.1 -Dpackaging=jar -Dfile=c:\path\to\jar\jta-1.1-classes.jar
    
  4. Bear with me, we are almost there
  5. cd into quickstart and run:
    Code Block
    $ mvn jetty:run
    
  6. Point your browser to http://localhost:8080/quickstart
  7. To create an eclipse project run:
    Code Block
    $ mvn eclipse:eclipse
    
    or (to create web project for WTP):
    Code Block
    mvn eclipse:eclipse -Dwtpversion=1.0
    

Doing it yourself

Create Eclipse project

  1. Open Eclipse. Seriously, you need to open Eclipse.
  2. Click File -> New -> Project. Under the "Web" folder, select "Dynamic Web Project" and click "Next".
  3. Enter the project name, "quickstart" from here on. The project will be running inside Tomcat, so we need to create a server configuration for it.
    1. Under "Target Runtime", click "New", select "Apache Tomcat 5.5" and click next.
    2. Enter Tomcat's installation directory and select an installed JRE (1.5 is required)
  4. Now you should be back to the project creation wizard, with Tomcat as your Target Runtime. Click "Next". Select "Dynamic Web Module" and "Java" facets, and click "Finish".

Dependencies

Your project should contain the folders "src", "build" and "WebContent". We are going to put all the required jars under "/WebContent/WEB-INF/lib". To add files to the "lib" folder, just copy them to ${workspace}\quickstart\WebContent\WEB-INF\lib, where ${workspace} is the location of your Eclipse workspace folder.

...

Right click on the project and select "Refresh" (to notify Eclipse of the jars that we just added).

Domain

Our domain model will consist of just a simple "Person" class with a couple of fields.

...

@Entity will let the provider know that this class can be persisted. @Id marks the "id" field as the primary key for this class. @GeneratedValue will cause the id field to be generated by the provider (Hibernate). Classes and fields are by default mapped to tables and columns with the same name, see JPA's documentation for more details.

Person service.

We will now write the class that will take care of CRUD operations on "Person" objects.

...

@PersistenceContext will make Spring inject an EntityManager into the service when it is instantiated. The @PersistenceContext annotation can be placed on the field, or on the setter method. If the class is annotated as @Transactional, Spring will make sure that its methods run inside a transaction.

JPA configuration

  1. Create a folder named "META-INF" under the "src" folder.
  2. Create a file named "persistence.xml" under the "META-INF" folder and set its content to:

...

JPA configuration can be set on this file. On this example it will be empty because the datasource configuration will be in the Spring configuration file.

Spring

  1. Update the content of web.xml under /WebContent/WEB-INF/web.xml to:

...

Note that the "class" attribute of the bean "personAction" is set to the name of the action class, and the "personService" bean will be passed as a parameter to the action constructor. Change the "url", "username" and "password" in the "dataSource" bean to the appropiate values for your database. For more details on the rest of the beans on this file, see Spring's documentation. The "scope" attribute is new in Spring 2, and it means that Spring will create a new PersonAction object every time an object of that type is requested. In Struts 2 a new action object is created to serve each request, that's why we need scope="prototype".

Struts

We will now create a simple Struts action that wraps PersonServices methods, and we will configure Struts to use Spring as the object factory.

...

Setting "struts.objectFactory" to "spring" will force Struts to instantiate the actions using Spring, injecting all the defined dependencies on applicationContext.xml. The "class" attribute for each action alias is set to "personAction", which is the bean id that we defined on applicationContext.xml for the PersonAction class. This is all that is needed to make Struts work with Spring.

The pages

We only have two pages, "index.jsp" and "list.jsp". "list.jsp" returns a table with a list of the persons on the database.We have this list on a different page because we are going to add some AJAX to spicy it up.

...

Look mom no page refresh!
The div "persons" will load its content asynchronously, and will show "Loading..." while while the request is on progress (you can use the "indicator" attribute for better progress feedback), you can force it to refresh clicking on the "Refresh" link. The "submit" button, will make an asynchronous request to the action "save" ("save" method on PersonAction), and will publish the topic "/save" to which we subscribed to, using "dojo.event.topic.subscribe", to clear the input fields.

Validation

Because we don't want any John Doe on our database, we will add some basic client side validation to our form. In Struts 2, validation can be placed on xml files with the name pattern ActionName-validation.xml, located on the same package as the action. To add validation to an specific alias of an action (like a method), the validation file name follows the pattern ActionName-alias-validation.xml, where "alias" is the action alias name (in this case a method name, "save"). Add a file named "PersonAction-save-validation.xml" under /src/quickstart/action, and set its content to:

...

To run the project, Right click on your project and Run As -> Run on Server. You can debug it on the same way, Right click on the project and Debug As -> Debug on Server. Download and install Struts 2 Showcase to see more examples.

Using Toplink Essentials instead of Hibernate

  1. Add this to pom.xml
    Code Block
    XML
    XML
     <repositories>
         <repository>
             <id>java.net</id>
             <url>https://maven-repository.dev.java.net/nonav/repository</url>
             <layout>legacy</layout>
         </repository>
     </repositories>
    
  2. Add this to the dependencies node in pom.xml
    Code Block
    XML
    XML
    <dependency>
         <groupId>toplink.essentials</groupId>
         <artifactId>toplink-essentials</artifactId>
         <version>2.0-38</version>
         <exclusions>
             <exclusion>
                 <groupId>javax.transaction</groupId>
                 <artifactId>jta</artifactId>
             </exclusion>
         </exclusions>
    </dependency>
    
  3. Replace the jpaVendorAdapter element in applicationContext.xml with this:
    Code Block
    XML
    XML
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
            <property name="databasePlatform" value="oracle.toplink.essentials.platform.database.MySQL4Platform" />
            <property name="generateDdl" value="true" /> 
            <property name="showSql" value="true" />
        </bean>
    </property>
    

References

Struts
Spring JPA Doc
JPA and Spring Tutorial
Eclipse Dali