Bookstore Example
The bookstore example shows how to build JAX-WS services with CXF and Mule. For information on using the CXF transport, see CXF Transport in the Mule User Guide (login required).
As of Mule 2.2, there is a webapp version of this example.
The bookstore example contains the following pieces:
- A bookstore JAX-WS service
- A bookstore client that can add, retrieve, and order books
- A Mule configuration that sets up the web service and email for order notifications
Running the Example
- Make sure you have met the prerequisites and installed Mule according to the Installing Mule instructions.
- At the command line, navigate to the examples/bookstore directory under your Mule home directory.
- Type bookstore.bat on Windows or ./bookstore on UNIX.
- Follow the on-screen prompts.
- To stop Mule, type 'CTRL-C' in the Mule console window.
Web Service
The web service consists of three parts:
- A Book class
- A Bookstore interface
- A Bookstore implementation
The Book class defines a simple datatype with fields such as title, author, and ISBN number.
The Bookstore interface defines the operations that make up the WSDL.
@WebService
public interface Bookstore
{
long addBook(@WebParam(name="book") Book book);
@WebResult(name="bookIds")
Collection<Long> addBooks(@WebParam(name="books") Collection<Book> books);
@WebResult(name="books")
Collection<Book> getBooks();
void orderBook(@WebParam(name="bookId") long bookId,
@WebParam(name="address") String address,
@WebParam(name="email") String email);
}
In addition to defining the various methods, it also has annotations. @WebService lets CXF know that this is a JAX-WS service. @WebResult & @WebParam are used to define the parameter names in the WSDL (Java does not store parameter names in the class files, so they must be supplied with annotations).
The implementation BookstoreImpl also stores Books in an in memory HashMap and manages the order process. It contains an important annotation:
@WebService(serviceName="BookstoreService",
portName="BookstorePort",
endpointInterface="org.mule.example.bookstore.Bookstore")
public class BookstoreImpl implements Bookstore
The @WebService annotation on the implementation will have the following effect:
- The endpointInterface attribute will control what interface CXF uses to build your WSDL. If this is not specified then CXF will use your web service implementation class to generate the WSDL - and hence expect any @WebParam/@WebResult annotations to be located there.
- The port name in the WSDL for this service will become "BookstorePort"
- The service name in the WSDL will be "BookstoreService"
The web service endpoint is declared in the Mule configuration like so:
<service name="echoService">
<inbound>
<inbound-endpoint address="cxf:http://localhost:8777/services/bookstore" />
</inbound>
<component>
<singleton-object class="org.mule.example.bookstore.BookstoreImpl" />
</component>
</service>
During the order processing the implementation also sends an email confirmation to the person who ordered the book. It does this by dispatching a new MuleMessage to the Mule email endpoint:
Book book = books.get(bookId);
MuleMessage msg = new DefaultMuleMessage(new Object[] { book, address, email} );
RequestContext.getEventContext().dispatchEvent(msg, "orderEmailService");
The payload being sent to the orderEmailService endpoint contains the book, the address to send the book to, and the email address to send a confirmation to. This payload then goes through 3 transformers:
1. MessagePropertiesTransformer: This extracts the email address from the payload and sets it as a property on the MuleMessage
2. OrderToEmail: This takes the message payload and converts it to a simple email message
3. StringToMimeMessage: This converts the email text to a MimeMessage suitable for sending over the JavaMail transport.
The flow for the email orderEmail service is defined in the EmailBridge service:
<service name="EmailBridge">
<inbound>
<inbound-endpoint ref="orderEmailService" />
</inbound>
<outbound>
<pass-through-router>
<smtps:outbound-endpoint user="username" password="password" host="smtp.gmail.com"
transformer-refs="SetAddress OrderToEmail StringToMimeMessage" connector-ref="emailConnector"
from="bookstore@mulesource.com" subject="Your order has been placed!" />
</pass-through-router>
</outbound>
</service>
Bookstore Client
The BookstoreClient class starts Mule and interacts with the web services in Mule using a simple web service client.
The web service client is created using the JaxWsProxyFactoryBean:
JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean();
pf.setServiceClass(Bookstore.class);
pf.setAddress("http:);
bookstore = (Bookstore) pf.create();
It also creates an initial book in the database:
Book book = new Book(1,"J.R.R. Tolkien","The Lord of the Rings");
bookstore.addBook(book);
The rest of the class is responsible for taking input from the user and sending that input to the web service, allowing you to add, retrieve and order books.