Sample Application using JAX-WS, JSF, Spring,
and Java Persistence APIs on Glassfish
eBay and Amazon provide Web Services APIs for developers who want to
provide access to these services in their web site. This Sample Store
Catalog application shows how to expose a
Service as a Web Service for remote client applications (this example
was not modeled after the eBay or Amazon APIs).
This example demonstrates a Catalog Spring
Bean, and the Java Persistence APIs to implement
a Catalog
Service which provides pagination of store items, and JAX-WS to
expose this Catalog
Service as a Web Service. A
separate example JSF JAX-WS client shows how this Catalog Web Service
can then
be used remotely in a sample Store web site. I took this
example
Sample
Application using JSF, Spring 2.0, and Java Persistence APIs and
modified the
Catalog Spring Bean to expose its public methods as Web Services, then
I put the JSF Store UI in a separate Web Application and modified it to
use
JAX-WS to call the Catalog Web Services.
Download
the Sample Application Code
Explanation of the usage of JAX-WS, JSF, Spring, and
Java Persistence
APIs in a sample Store Catalog Application
The image below shows the Catalog Listing page, which allows a user to
page through a list of items
in a store.
Explanation of the Catalog Web Service which uses JAX-WS, JPA,
and Spring 2.0
The
Catalog
Spring Bean uses a JPA
EntityManager
Query
object to return a list of
items.
With
the
@PersistenceContext annotation,
the CatalogBean uses dependency injection to lookup and obtain a
Container Managed
EntityManager (note that
using the
@PersistenceContext annotation is the same
way an
Entity Manager is injected for a
EJB
3.0 Session Bean.)
.
The
@WebService
annotation marks this class as a web service, and causes any public
methods to be exposed as Web Services. The example JSF Web
Service client uses the
Catalog
Web Service
getItems
method to get the
Items
for displaying on the Web Store UI . (Note:
Red colors
are for
Java EE
tags, annotations code,
Blue for
Spring
and
Green
for
my code
or
variables)
Code Sample from: Catalog.java |
@WebService
@Repository
@Transactional
public class Catalog
implements CatalogService
{
@PersistenceContext(unitName="PetCatalogPu")
private EntityManager em;
public List<Item> getItems(int
firstItem,int batchSize) {
Query q = em.createQuery("select
object(o) from Item as o");
q.setMaxResults(batchSize);
q.setFirstResult(firstItem);
List<Item>
items= q.getResultList();
return items;
}
|
The code below shows the
Item
entity class which maps to the ITEM table that stores the
item instances. This is a
typical Java Persistence entity object. For more information on
this code see
this
previous blog.
Code Sample from: Item.java |
@Entity
public class Item
implements java.io.Serializable {
@Id
private String itemID;
private String name;
private String description;
private String imageurl;
private BigDecimal price;
@OneToOne(cascade={CascadeType.PERSIST})
private Address address;
public Item() { }
public String getItemID() {
return itemID;
}
public void setItemID(String itemID) {
this.itemID = itemID;
}
// getters and setters for
other item attributes
...
}
|
When this application is deployed, the JAXB, JAX-WS, and
WSDL files needed for the Service will be generated on the
server. You can access the
Catalog WSDL
contract at this URL:
http://localhost:8080/SpringWS-war/CatalogService?wsdl
. Below is part of the WSDL, you can see that the
Catalog class
name defaults to the
portType
name and the
getItems method
name defaults to the
operation
name (defaults can be changed using annotations, see
the
Java EE tutorial for more information).
| Code Sample from: CatalogService.wsdl |
<portType
name="Catalog">
<operation
name="getItems">
<input
message="tns:getItems"/>
<output
message="tns:getItemsResponse"/>
</operation>
</portType>
...
<service name="CatalogService">
<port name="CatalogPort"
binding="tns:CatalogPortBinding">
<soap:address
location="http://host:8080/SpringWS-war/CatalogService" />
</port>
</service>
|
Here
is part of the generated xml Schema for the WSDL getItems response
message:
| Code Sample from: CatalogService.xsd |
<xs:complexType name="getItemsResponse">
<xs:sequence>
<xs:element name="return"
type="tns:item" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="item">
<xs:sequence>
<xs:element name="address"
type="tns:address" minOccurs="0"/>
<xs:element name="contactinfo"
type="tns:sellercontactinfo" minOccurs="0"/>
<xs:element name="description"
type="xs:string" minOccurs="0"/>
<xs:element name="disabled"
type="xs:int"/>
<xs:element name="imagethumburl"
type="xs:string" minOccurs="0"/>
<xs:element name="imageurl"
type="xs:string" minOccurs="0"/>
<xs:element name="itemid"
type="xs:string" minOccurs="0"/>
<xs:element name="name"
type="xs:string" minOccurs="0"/>
<xs:element name="numberofvotes"
type="xs:int"/>
<xs:element name="price"
type="xs:decimal" minOccurs="0"/>
<xs:element name="totalscore"
type="xs:int"/>
</xs:sequence>
</xs:complexType>
|
and the corresponding generated JAXB class:
Code Sample from: GetItemResponse.java |
@XmlRootElement(name
= "getItemResponse")
@XmlType(name = "getItemResponse")
public class GetItemResponse {
@XmlElement(name = "return")
private Item _return;
public Item getReturn() {
return this._return;
}
public void setReturn(Item _return) {
this._return = _return;
}
...
}
|
JAX-WS delegates all data binding functionality to JAXB 2.0:
After deployment on Glassfish you can access a web client tester
application provided by the
Glassfish Application Server at the URL for the Web Service
followed by "?Tester" for example :
http://host:8080/SpringWS-war/CatalogService?Tester. Below is the Web
Service Tester interface for the CatalogService. It provides an easy
way to call the Web Service operations from a browser.
Here is an example soap request and response for the getItems
WebService operation:
SOAP Request
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<ns1:getItems>
<arg0>0</arg0>
<arg1>2</arg1>
</ns1:getItems>
</soapenv:Body>
</soapenv:Envelope>
SOAP Response
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns1:getItemsResponse>
<return>
<address>
<addressid>1</addressid>
<city>Mountain View</city>
<latitude>37.3857400000</latitude>
<longitude>-122.0839730000</longitude>
<state>CA</state>
<street1>Castro St</street1>
<street2/>
<zip>94040</zip>
</address>
<description>super friendly</description>
<itemid>1</itemid>
<name>Friendly Cat</name>
<numberofvotes>3</numberofvotes>
<price>307.10</price>
<totalscore>15</totalscore>
</return>
<return>
<address>
<addressid>2</addressid>
<city>Foster City</city>
<latitude>37.5469350000</latitude>
<longitude>-122.2639780000</longitude>
<state>CA</state>
<street1>Shell Blvd & Beach Park Blvd</street1>
<street2/>
<zip>94404</zip>
</address>
<description>A great pet</description>
<itemid>2</itemid>
<name>Friendly Cat</name>
<numberofvotes>3</numberofvotes>
<price>307.00</price>
<totalscore>15</totalscore>
</return>
</ns1:getItemsResponse>
</soapenv:Body>
</soapenv:Envelope>
Explanation of the JSF Store UI which uses JAX-WS to call the
Catalog Web Service.
The JSF Store UI is a separate web application which is a JAX-WS
client.
The List.jsp page uses a JSF
dataTable
component to display a list of
catalog items. The dataTable component is useful when you want to show
a set of
results in a table.
In the
List.jsp
web page the dataTable is defined as shown below:
Code Sample from: List.jsp |
<h:dataTable value='#{item.items}' var='dataTableItem'
border="1"
cellpadding="2" cellspacing="0">
|
The
value attribute of a
dataTable
tag references the data to be included
in the table. The
var
attribute points
to a single item in that list. As the
dataTable
JSF component iterates through the
list, each reference to
dataTableItem points to the current item in the
list.
The
dataTable's
value
is bound to the
items
property
of the
ItemController
managed-bean class,
which is defined in the
faces-config.xml
| Code Sample from: faces-context.xml |
<application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>
</application>
<managed-bean>
<managed-bean-name>item</managed-bean-name>
<managed-bean-class>
sessionpagination.ItemController
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
|
The
recommended way to integrate Spring with JSF is to
configure the Spring
DelegatingVariableResolver
in the
faces-context.xml. The <application>
<variable-resolver>
elements in a faces-config.xml file allows a Faces-based application to
register a custom replacement class for the implementation of the
standard Faces VariableResolver
implementation. The Spring DelegatingVariableResolver
first delegates to the original resolver of the underlying JSF
implementation, then to the Spring root
WebApplicationContext.
This ItemController ManagedBean
items
property is defined as shown below (the
orange color
highlights the
JAX-WS
dynamic proxy classes and methods):
| Code Sample from: ItemController.java |
public class ItemController
{
@WebServiceRef(wsdlLocation
= "http://localhost:8080/CatalogService/Catalog?wsdl")
private CatalogService
service;
public DataModel getItems() {
if (model==null || index !=
firstItem){
model=getNextItems();
}
return this.model;
}
public DataModel
getNextItems() {
Catalog port = service.getCatalogPort();
model = new ListDataModel(port.getItems(
firstItem,batchSize));
return model;
}
|
The
ItemController
ManagedBean uses dependency injection to obtain a reference to the
CatalogService
JAX-WS proxy factory class, which is generated from the Catalog WSDL
file using the wsimport utility. (To see how to do this easily with
Netbeans see the
Netbeans Web
Services (JAX-WS) in Java EE 5 tutorial). The
ItemController
retrieves a proxy to the service by calling
getCatalogPort()
on the
CatalogService,
which returns the
Catalog Service
Endpoint Interface. The proxy implements the
Catalog Service
Endpoint Interface defined by the
Catalog
service. The
ItemController can
then invoke the port’s
getItems
method. The dynamic proxy and jaxb classes convert the WS method
into a SOAP request and send it to the Web service's endpoint,
receive the SOAP response, and transform the SOAP response into the
java method's return object which in this case is a
List<Item>.
The
getItems()
method wraps a List of items, returned from the
Catalog Service,
in a
DataModel.
The
dataTable JSF
component supports data binding to a
collection of data objects represented by a
DataModel
instance. The data
collection underlying a DataModel instance is modeled as a collection
of row objects that can be accessed by a row index. The APIs
provide mechanisms to position to a specified row index, and to
retrieve an object that represents the data that corresponds to the
current row index.
The Name, Photo, and Price
item
properties are displayed with the
JSF
column
component:
Code Sample from: List.jsp
|
<h:column>
<f:facet name="header">
<h:outputText
value="Price"/>
</f:facet>
<h:outputText
value="#{dataTableItem.price}"/>
</h:column>
|
The column tags represent columns of data in a
dataTable.
The
dataTable JSF component iterates
through the list of
items
(
item.
items) each time rendering
one cell in
each column and displaying the
item name, photo, and
price.
For more information on
the JSF part of this code see
this
previous blog.
Configuration of
the XML files for Spring 2.0, JSF, and JPA, running on Glassfish
- The /WEB-INF/applicationContext.xml file
is where you define your Spring
service beans, and resources. Below is the applicationContext.xml for
the sample Catalog app. For
more information about configuring the Spring
applicationContext.xml for JPA see this article: Using the Java
Persistence API (JPA) with Spring 2.0
| Code Sample from: applicationContext.xml
|
<?xml
version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean id="catalogService"
class="service.Catalog"/>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property
name="dataSource" ref="dataSource"/>
<property
name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.glassfish.GlassFishLoadTimeWeaver"/>
</property>
<property
name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform"
value="oracle.toplink.essentials.platform.database.DerbyPlatform"
/>
</bean>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property
name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"
/>
<property name="url"
value="jdbc:derby://localhost:1527/pet-catalog"
/>
<property name="username"
value="app" />
<property name="password"
value="app" />
</bean>
<bean
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property
name="entityManagerFactory" ref="entityManagerFactory"/>
<property
name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven />
</beans>
|
| Code Sample from: web.xml
|
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
|
- For the JSF UI and Spring add the
DelegatingVariableResolver
to the faces-config.xml :
| Code Sample from: faces-config.xml
|
<application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>
</application>
<managed-bean>
<managed-bean-name>item</managed-bean-name>
<managed-bean-class>
sessionpagination.ItemController
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
|
Conclusion
The sample Store Catalog application demonstrates how to
expose Spring bean
methods
which use the
Java
Persistence APIs as Web Service operations using
JAX-WS.
The sample JSF Store UI application demonstrates how to use
the
JSF dataTable and
DataModel
to page through a
list
of
Items
which are retrieved from the
Catalog Service
using
JAX-WS.
Running the Sample Application on
Glassfish:
Setting Things Up
- Download and install NetBeans
5.5.1.
- Download and unzip Spring 2.1 (download the with dependencies
version).
- Download and install GlassFish V1.
Alternatively you can use Sun Java System
Application Server PE 9, Sun's binary distribution of GlassFish.
- Add the GlassFish server to NetBeans:
- Start NetBeans and switch to the Runtime window (Ctrl+5).
- Right-click the Servers node and select Add Server.
- Select Sun Java System Application Server.
- Browse to the location where you installed GlassFish and
select Finish
Create the Spring Library in NetBeans
- Open the NetBeans Library Manager (in the Tools menu) and create
a new library called Spring.
- Add the following jars to the class path:
dist/spring.jar
dist/weaving/spring-aspects.jar
lib/jakarta-commons/commons-logging.jar
lib/log4j/log4j-1.2.9.jar .
- Set the Sources to the Spring
src directory.
- Set the Javadoc to the Spring
docs\api directory.
Open and Run the Sample code SpringWS:
- Download the
Sample Application Code SpringWS.zip and SpringWSClient.zip and
extract their contents. You should now see the newly extracted
directory as
<sample_install_dir>/SpringWS, and <sample_install_dir>/SpringWSClient,
where <sample_install_dir> is the directory where
you installed the sample package. For example, if you extracted the
contents to C:\ on a Windows machine, then your newly
created directory should be at C:\SpringWS.
- Start the NetBeans IDE. Click Open Project in the File menu and
select the
SpringWS directory you just unzipped. The SpringWS
application is a NetBeans Enterprise Application Project, which is
actually comprised of two projects: SpringWS and SpringWS-war.
SpringWS-war is a Java EE Module of the SpringWS
project. SpringWS-war generates the war file and SpringWS
generates the ear file which contains the war.
You will see a Reference Problems dialog when you open the project.
That's because the Enterprise Application Project stores the absolute
location to its J2EE Modules. To resolve the reference problems, you
need to configure the location for the SpringWS-war.
However, first click Close in the dialog. The SpringWS
project will be in bold red meaning that it still has reference
problems.
- Right click the
SpringWS project and select Resolve
Reference Problems from the context menu. Use the Resolve Reference
Problems dialog to map the SpringWS-war module to its
project, which you'll find is a subdirectory beneath the SpringWS
directory.
- Right click the
SpringWS project and select Open
Required Projects. Now that the dependencies are correct, the SpringWS-war
project will always open with the SpringWS
project. However, there are additional references problems with the web
module because it references the Spring jar files that are needed to
build the project.
- Add the Spring library to the
SpringWS-war. In the
Project window under SpringWS-war:
- Right click on Libraries and select Add Library.
- Select the Spring Library in the list, then click Add Library.
- Edit the properties in the
SpringWS\setup\javadb.properties
file, as appropriate.
- Start the Java DB database as follows:
- Select Java DB Database in the Tools menu.
- Select Start Java DB Server.
- Build the project as follows:
- Right click the
SpringWS node in the Projects
window.
- Select Build Project.
- Run the project as follows:
- Right click the
SpringWS node in the Projects
window.
- Select Run Project.
When you run the project, your browser should display the web service
client Tester
application provided by the
Glassfish Application Server at the url :
http://localhost:8080/SpringWS-war/CatalogService?Tester .
You should see the
tester page. For the getItems operation type in integer the integers 0,
5 as input and click on the getItems button. This will return a list
of items 0 through 5.

If this does not work,
- Right click the
SpringWS node in the Projects
window.
- Select Deploy Project.
then open the browser and use the url
http://host:8080/CatalogService/Catalog?wsdl , this will display the
wsdl if the application deployed correctly. Then try the web service
test client url
http://localhost:8080/SpringWS-war/CatalogService?Tester .
Open and Run the Sample code WSClient:
- In Netbeans Click Open Project in the File menu and
select the
SpringWSClient directory you just unzipped.
The SpringWSClient project is a web
project which creates the SpringWSClient-war.
- Add the Spring library to the
SpringWSClient
. In the
Project window under SpringWSClient
:
- Right click on Libraries and select Add Library.
- Select the Spring Library in the list, then click Add Library.
- Build the project as follows:
- Right click the
SpringWSClient
node in the Projects
window.
- Select Build Project.
- Run the project as follows:
- Right click the
SpringWSClient
node in the Projects
window.
- Select Run Project.
When you run the project, your browser should display the
opening page
of the JSF, JAX-WS, Java Persistence API, and Spring 2.0 Sample
Application (at http://localhost:8080/SpringWSClient/
)
References: