 |
Sample Application using JAX-WS, JSF, EJB 3.0, and Java
Posted by caroljmcdonald on September 18, 2007 at 08:43 PM | Comments (4)
Sample Application using JAX-WS, JSF, EJB 3.0,
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 Stateless Session
Bean, and the Java Persistence APIs to implement
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 Pagination
of Data Sets in a Sample Application using JSF, Catalog Facade
Stateless Session, and Java Persistence APIs and modified the
Catalog Session 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, EJB 3.0, 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 EJB 3.0
The Catalog
Session EJB 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 .
The @Stateless
annotation marks this class as a Stateless Session EJB.
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,
and Green
for my code
or variables)
Code Sample from: Catalog.java |
@WebService
@Stateless
public class Catalog
implements CatalogService {
@PersistenceContext(unitName="PetCatalogPu")
private EntityManager em;
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
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;
@ManyToOne
private Product product;
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://host:8080/CatalogService/Catalog?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/CatalogService/Catalog" />
</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="product"
type="tns:product" 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/CatalogService/Catalog?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"?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Header/> <S:Body> <ns2:getItems xmlns:ns2="http://model.sessionpagination/"> <arg0>0</arg0> <arg1>2</arg1> </ns2:getItems> </S:Body> </S:Envelope>
SOAP Response
<?xml version="1.0" encoding="UTF-8"?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:getItemsResponse xmlns:ns2="http://model.sessionpagination/"> <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> <contactinfo> <contactinfoid>1</contactinfoid> <email>abc@abc.xyz</email> <firstname>Sean</firstname> <lastname>Brydon</lastname> </contactinfo> <description>super friendly</description> <itemid>1</itemid> <name>Friendly Cat</name> <numberofvotes>3</numberofvotes> <price>307.10</price> <product> <category> <categoryid>CATS</categoryid> <description>Loving and finicky friends</description> <name>Cats</name> </category> <description>Great for reducing mouse populations</description> <name>Hairy Cat</name> <productid>feline01</productid> </product> <totalscore>15</totalscore> </return> <return> <address> ... </address> <contactinfo> ... </contactinfo> <itemid>2</itemid> <name>Fluffy Cat</name> <product> <category> <categoryid>CATS</categoryid> ... </category> <name>Hairy Cat</name> <productid>feline01</productid> </product> </return> </ns2:getItemsResponse> </S:Body> </S: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 |
<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>
|
This ItemController ManagedBean items
property is defined as shown below (the blue 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.
Conclusion
The sample Store Catalog application demonstrates how to
expose
EJB 3.0 Stateless Session EJB
methods
which use the
Java
Persistence APIs as a 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:
- Download
and install GlassFish V2, following the instructions on the download
page. Alternatively you can use Sun Java System Application Server PE
9, Sun's GlassFish distribution.
- Download
and install NetBeans 5.5.1
-
Download
the Sample Application Code
- install Glassfish and Netbeans 5.5.1. Then add the
glassfish application server to Netbeans.
To Open and Test Run the sessionpagination Project:
- Open the Netbeans sessionpagination project: In Netbeans under
File Open Project... go to the directory where you unzipped the sample
and select the sessionpagination project.
- If you get a message that says unresolved references, right click
on the project and select Resolve Reference Problems. Use the Resolve
Reference Problems dialog to map the ejb and web
modules to their
project, which are subdirectories beneath the sessionpagination
directory.
- After the references are resolved, right-click the
sessionpagination
project and select Open Required Projects.
- If the web module says unresolved references, right-click the
sessionpagination-Web module and select Resolve
Reference
Problems:
- Browse to the sessionpagination-ejb directory which is a
sub-directory below the sessionpagination directory and select Open
Project
Folder.
- If you don't have any resolve reference problems errors then
ignore those steps.
- Starts the application server, or at least connect to the
database, because the run script for this application will also create
the database tables, and this will fail if the database is not started.
- Right-click the project node and choose Run Project.
The Netbeans IDE starts the application server, builds the application,
and opens the web context page in your browser. This application also
has a local JSF client in the war of the application which will be
displayed.
- To go to the web client Tester
application provided by the
Glassfish Application Server use the url :
http://host:8080/CatalogService/Catalog?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.
To Open and Test Run the sessionpagination-wsclient Project:
- Open the Netbeans sessionpagination-wsclient project: In Netbeans
under File
Open Project... go to the directory where you unzipped the sample and
select the sessionpagination-wsclient project.
- Right-click the project node and choose Run Project.
The Netbeans IDE builds the application,
and deploys it.
- When you run the project, your browser should display the opening
page
of the application at http://localhost:8080/sessionpagination-wsclient/
References:
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
this is very good
Posted by: sushilpanday on September 27, 2007 at 11:05 AM
-
Hey, thanks!
Posted by: caroljmcdonald on September 28, 2007 at 12:48 PM
-
Mrs Carol, I definitely need your help...
I have made a enterprise project with netbeans IDE (smile as Java EE module, smile-war as web application module and smile-ejb as EJB module). I made entity from database REGISTRASI_SMILE in ejb module. and then I made CRUD (create, read, update and delete) application with JSF in web application module and call entity database REGISTRASI_SMILE . There is something problem when I access List.jsp and give information below here in my web browser:
javax.servlet.ServletException:
Exception Description: A problem was encountered resolving the class name - The descriptor for [RegistrasiSmile] was not found.
javax.faces.webapp.FacesServlet.service(FacesServlet.java:256)
com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:73)
com.sun.enterprise.web.VirtualServerPipeline.invoke(VirtualServerPipeline.java:120)
org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:231)
com.sun.enterprise.web.connector.grizzly.ProcessorTask.invokeAdapter(ProcessorTask.java:667)
com.sun.enterprise.web.connector.grizzly.ProcessorTask.processNonBlocked(ProcessorTask.java:574)
com.sun.enterprise.web.connector.grizzly.ProcessorTask.process(ProcessorTask.java:844)
com.sun.enterprise.web.connector.grizzly.ReadTask.executeProcessorTask(ReadTask.java:287)
com.sun.enterprise.web.connector.grizzly.ReadTask.doTask(ReadTask.java:212)
com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:252)
com.sun.enterprise.web.connector.grizzly.WorkerThread.run(WorkerThread.java:75)
....
Actually, CRUD application made JSF is completely running if entity from database place in web application module like tutorial made by Sang Shin (Java EE 5 Basics: Web Services, EJB 3.0, Java Persistence API, JSF). But I still need enterprise module to develop session bean-web services. What should I do ?
Posted by: milanelum on December 22, 2007 at 09:17 PM
-
I had trouble searching for the commons.loggin-1.1.jar, and the bp-ui-14.jar, and the shale-remoting.jar. Could you please add a link to these libraries?
Posted by: marcnoon37 on February 29, 2008 at 01:58 PM
|