Access Keys:
Skip to content (Access Key - 0)

Contents

Bookstore Webapp Example

The bookstore webapp example demonstrates how to:

  • Run Mule ESB inside a Webapp
  • Use Mule with the Servlet transport
  • Use Mule with CXF web services

You can read more about the Servlet transport and CXF Transport in the Mule User Guide (login required).

Note: The bookstore webapp example was added in Mule 2.2 as an evolution of the older Bookstore Example. The bookstore webapp example is still in beta. Please file a JIRA for any problems you encounter, or better yet, submit fixes for them! For more information, see Getting Involved.

Overview of the Bookstore Example

To watch a webinar that walks through the bookstore example, go to http://www.mulesoft.com/webinar-make-web-applications-do-more-mule.

The bookstore example includes the following:

  • A bookstore catalog service with a public interface for browsing the catalog and an admin interface for adding books to the catalog
  • An order service that allows customers to order books
  • An email notification service that sends an email when an order has been placed.
  • A data warehouse service that tracks statistics on the books, such as the number of books sold, total revenue, and best sellers.

The example is contained within three modules:

  • The API module contains the domain objects and interfaces used by the two webapps.
  • The Admin webapp includes the Mule configuration file and the service definitions. This module is hosted behind the firewall.
  • The Bookstore webapp includes the JSPs for displaying the catalog to customers outside of the firewall.

Following is an overview of the architecture:

Running the Example

To run the Bookstore example, run the mvn tomcat:run command in the admin-web and bookstore-web subdirectories under the <MuleHome>\examples\bookstore directory. The applications will then be available at the following URLs:

Service Details

These services are defined in the bookstore-config.xml file in the examples\bookstore\admin-web\src\main\resources directory. All four services are in a single model called Bookstore:

<model name="Bookstore">

  <service name="CatalogService">
    <inbound>
      <!-- Public interface -->
      <inbound-endpoint address="cxf:http://localhost:8777/services/catalog" />

      <!-- Administration interface -->
      <inbound-endpoint address="servlet://catalog">                                      
        <transformers>                                  
          <!-- Extract parameters from HTTP Request -->
	  <servlet:http-request-to-parameter-map />
	  <!-- Convert request parameters to Book object -->
	  <custom-transformer class="org.mule.example.bookstore.transformers.ParameterMapToBook"/>
        </transformers>
        <response-transformers>
          <!-- Format response to be a nice HTML page --> 
	  <custom-transformer class="org.mule.example.bookstore.transformers.AddBookResponse"/>
        </response-transformers>
      </inbound-endpoint>
    </inbound>
    <component>
      <singleton-object class="org.mule.example.bookstore.CatalogServiceImpl" />
    </component>
  </service> 

  <service name="OrderService">
    <inbound>
      <!-- Public interface -->
      <inbound-endpoint address="cxf:http://localhost:8777/services/order" />
    </inbound>
    <component>
      <singleton-object class="org.mule.example.bookstore.OrderServiceImpl" />
    </component>
    <outbound>
      <multicasting-router>
        <vm:outbound-endpoint path="emailNotification"/>
        <vm:outbound-endpoint path="dataWarehouse"/>
      </multicasting-router>
    </outbound>
  </service>
          
  <service name="EmailNotificationService">
    <inbound>
      <vm:inbound-endpoint path="emailNotification" />
    </inbound>
    <outbound>
      <pass-through-router>
        <smtp:outbound-endpoint user="username" password="password" host="smtp.gmail.com" 
          from="bookstore@mulesource.com" subject="Your order has been placed!">
          <transformers>
	    <custom-transformer class="org.mule.example.bookstore.transformers.OrderToEmailTransformer" />
	    <email:string-to-email-transformer />
          </transformers> 
        </smtp:outbound-endpoint>
      </pass-through-router>
    </outbound>
  </service>
          
  <service name="DataWarehouse">
    <inbound>
      <vm:inbound-endpoint path="dataWarehouse"/>
    </inbound>
    <component>
      <singleton-object class="org.mule.example.bookstore.DataWarehouse" />
    </component>
    <outbound>
      <pass-through-router>
        <outbound-endpoint ref="stats" />
      </pass-through-router>
    </outbound>
  </service>
</model>
...

Admin Webapp

When an administrator adds a book in the Admin application, the information in the web page is sent as an HTTP request using the POST method <form method="POST" action="../catalog"> over the Servlet transport to servlet://catalog. Mule then transforms the HTTP request to a Book object, which is passed via the addBook method to the Catalog service.

The Admin webapp web.xml file, located in the examples\bookstore\admin-web\src\main\webapp\WEB-INF directory under your Mule directory, provides the Mule configuration as a context parameter so that Mule can be started within the webapp:

<web-app>
    <display-name>Bookstore Administration</display-name>
    <description>Administration console for the Mule-powered On-line Bookstore</description>

	<!-- The Mule configuration is provided as a context parameter -->
    <context-param>
        <param-name>org.mule.config</param-name>
        <param-value>bookstore-config.xml</param-value>
    </context-param>

	<!-- This listener will start up Mule inside the webapp -->
    <listener>
        <listener-class>org.mule.config.builders.MuleXmlBuilderContextListener</listener-class>
    </listener>
...

The JSP used to construct the web page, admin.jsp, is located in the examples\bookstore\admin-web\src\main\webapp directory.

Bookstore Webapp

When a customer searches the catalog through the bookstore web application, the getBooks() method is called on the Catalog service. The request is sent over the CXF transport cxf:http://localhost:8777/services/catalog, which marshalls the request between Java and WSDL/XML. The Catalog service replies with the Book object, which is sent back as an XML response marshalled by CXF, and the result is displayed in the HTML page.

The Bookstore webapp web.xml file, located in the examples\bookstore\bookstore-web\src\main\webapp\WEB-INF directory under your Mule directory, loads the catalog JSP to display in the HTML page to customers:

<web-app>
    <display-name>On-line Bookstore</display-name>
    <description>Mule-powered On-line Bookstore</description>

    <welcome-file-list>
        <welcome-file>catalog.jsp</welcome-file>
    </welcome-file-list>
</web-app>

The HTML page looks like this:

Java Classes

The Java classes for the Admin webapp are located in examples\bookstore\admin-web\src\main\java\org\mule\example\bookstore. The CatalogServiceImpl.java class defines the methods for adding and getting books. The OrderServiceImpl.java class defines the orderBook() method. The DataWarehouse.java class defines methods for updating statistics on the page, retrieving the best seller, and printing the statistics on the page.

The domain objects such as Book and Order are defined in Java classes in examples\bookstore\api\src\main\java\org\mule\example\bookstore.

In addition to defining the various methods, the Java files also contain annotations. @WebService lets CXF know that this is a JAX-WS service. For example, CatalogServiceImpl.java contains the following annotation:

@WebService(serviceName="CatalogService", endpointInterface="org.mule.example.bookstore.CatalogService")

The serviceName attribute specifies that the service name in the WSDL will be "CatalogService". The endpointInterface attribute will control what interface CXF uses to build your WSDL. If this is not specified, CXF will use your web service implementation class to generate the WSDL and therefore expects any @WebParam and @WebResult annotations to be located there.

The @WebResult and @WebParam annotations 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):

@WebResult(name="order") 
  Order orderBook(@WebParam(name="book") Book book, 
    @WebParam(name="quantity") int quantity, 
    @WebParam(name="address") String address,
    @WebParam(name="email") String email);

Transformers

The examples\bookstore\admin-web\src\main\java\org\mule\example\bookstore\transformers directory contains the transformers that do the following:

  • Adds a book to the response message and wraps it in an HTML body using the HTML template in examples\bookstore\admin-web\src\main\java\org\mule\example\bookstore\web.
  • Composes an e-mail notification message to be sent based on the Book Order. The <string-to-email-transformer> from the Email transport is then used to convert the text to an email message.
  • Transforms a Map of HttpRequest parameters into a Book object.
Adaptavist Theme Builder Powered by Atlassian Confluence