The Simple Messaging Framework  

The Simple Messaging Framework

Tutorial

Author: Naresh Bhatia (nbhatia@sapient.com)
Created: July 2003
Version: $Revision: 1.1 $ ($Author: nbhatia $ / $Date: 2003/07/21 03:30:50 $)

Introduction

This tutorial describes the process of creating and accessing a Web service using the Simple Messaging Framework. We will start with a Calendar application which provides an interface for scheduling meetings. We will first expose this interface as a Web service and then access it from a client application.

Calendar Application

The Calendar application is a hypothetical application used for maintaining user calendars and scheduling meetings among these users. The application provides a Java interface for scheduling meetings. This interface is called MeetingService and is shown below.

MeetingService API
package org.calendarapp.meetingservice;
public interface MeetingService {
    public String createMeeting(Meeting meeting);
    public Meeting getMeeting(String meetingId);
    public void addAttendee(String meetingId, Attendee attendee);
    public void removeAttendee(String meetingId, String username);
    public void deleteMeeting(String meetingId);
}

The MeetingService API uses Meeting and Attendee classes. These classes are shown in the diagram below. Note that a Meeting can have many Attendees.

The tutorial supplies some starter code for the Calendar application. We will first compile this code and run a test to ensure that the MeetingService API is functioning correctly. We will then expose this API as a Web service and finally access it using a Web service client.

Build the Application

  1. If you have not yet installed the Simple Messaging Framework, please do so by following the Installation Guide.
  2. The Calendar application requires Tomcat 4.1.24 or later. If you do not have Tomcat, please download it and install it on your machine.
  3. Make a copy of the Tutorial directory located at smfw/samples/Tutorial. Use this copy to work through the tutorial. We will refer to this copy as the prj.dir.
  4. Edit the file prj.dir/ant.developer.properties to make sure it has the correct directory paths for your environment. If you have installed your libraries at locations recommended by the Installation Guide, then you may need to edit only one path - the lib.dir.
  5. Open a command shell and change the current directory to prj.dir
  6. .
  7. Execute the following command to build the Calendar application:
    ant build
  8. Execute the following command to test the Calendar application:
    ant test

If you see the following output you have built the Calendar application successfully. You may wish to take a quick look at prj.dir/server/meeting-service to see how the MeetingService is implemented.

[junit] Creating a meeting...

[junit] meetingId: 1
[junit] subject: Project kickoff
[junit] location: Room 203
[junit] startTime: 07-13-2003 23:49:44
[junit] endTime: 07-13-2003 23:49:44
[junit] organizer: jdoe
[junit] body:
[junit] Let's get the ball rolling!
[junit] attendees:
[junit] jmagic, isRequired=false, status=not_responded
[junit] phead, isRequired=true, status=not_responded
[junit] thacker, isRequired=false, status=not_responded
[junit] jdoe, isRequired=true, status=accepted

[junit] Adding attendee jsmith...

[junit] meetingId: 1
[junit] subject: Project kickoff
[junit] location: Room 203
[junit] startTime: 07-13-2003 23:49:44
[junit] endTime: 07-13-2003 23:49:44
[junit] organizer: jdoe
[junit] body:
[junit] Let's get the ball rolling!
[junit] attendees:
[junit] jmagic, isRequired=false, status=not_responded
[junit] phead, isRequired=true, status=not_responded
[junit] thacker, isRequired=false, status=not_responded
[junit] jsmith, isRequired=true, status=not_responded
[junit] jdoe, isRequired=true, status=accepted

[junit] Removing attendee jmagic...

[junit] meetingId: 1
[junit] subject: Project kickoff
[junit] location: Room 203
[junit] startTime: 07-13-2003 23:49:44
[junit] endTime: 07-13-2003 23:49:44
[junit] organizer: jdoe
[junit] body:
[junit] Let's get the ball rolling!
[junit] attendees:
[junit] phead, isRequired=true, status=not_responded
[junit] thacker, isRequired=false, status=not_responded
[junit] jsmith, isRequired=true, status=not_responded
[junit] jdoe, isRequired=true, status=accepted

[junit] Deleting the meeting...
[junit] Testsuite: org.calendarapp.meetingservice.test.MeetingServiceTest
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.441 sec

Define Messages

For the purpose of this tutorial, we will expose the createMeeting() method of the API. This method accepts a Meeting object (with the meetingId set to null), creates the meeting, and finally returns the meetingId assigned to the meeting. As suggested in the Architecture document, the starter code defines a request message and a response message corresponding to this method. The request message is called CreateMeetingMessage and encapsulates the meeting that needs to be created. The response message is called MeetingIdMessage and encapsulates the meetingId that will be returned. Review these messages under prj.dir/common/src/org/calendarapp/message.

Write the WSDL

The starter code already supplies a WSDL document with definitions for the CreateMeetingMessage and the MeetingIdMessage. Review the WSDL document located at prj.dir/server/soap-server/WEB-INF/classes/meeting-service.wsdl.

Implement the MessageReader and MessageWriter Interfaces

The starter code supplies implementations of the MessageReader and MessageWriter interfaces. It uses an XML pull parser called XPP for these implementations. XML pull parsers are very easy to work with and very efficient. Review the MessageReader and MessageWriter implementations at prj.dir/common/src/org/calendarapp/messageio. Also review the configuration file located at prj.dir/server/config/smfw/MessagingEngineConfiguration.xml where we inform the framework about these implementations.

Implement a MessageHandler

At this point we have all the machinery needed to send a CreateMeetingMessage from a client to a server. We now need a handler for the server to handle the CreateMeetingMessage. This handler is shown below. It calls the MeetingService to create the supplied meeting and returns the meetingId packaged into a MeetingIdMessage. Create this handler at prj.dir/server/soap-server/src/org/calendarapp/messagehandlers/CreateMeetingMessageHandler.java.

CreateMeetingMessageHandler.java
package org.calendarapp.messagehandlers;

import org.calendarapp.meetingservice.MeetingService;
import org.calendarapp.meetingservice.MeetingServiceException;
import org.calendarapp.meetingservice.MeetingServiceImpl;
import org.calendarapp.message.CreateMeetingMessage;
import org.calendarapp.message.MeetingIdMessage;
import org.sape.smfw.message.Message;
import org.sape.smfw.messagingengine.MessageContext;
import org.sape.smfw.messagingengine.MessageHandler;
import org.sape.smfw.messagingengine.MessageHandlerException;
import org.sape.smfw.messagingengine.MessagingEngineException;

public class CreateMeetingMessageHandler implements MessageHandler {

    public Message handleMessage(MessageContext messageContext, Message message)
    throws MessagingEngineException {

        try {
            CreateMeetingMessage msg = (CreateMeetingMessage)message;

            // Create the supplied meeting
            MeetingService meetingService = new MeetingServiceImpl();
            String meetingId =
                meetingService.createMeeting(msg.getMeeting());

            return new MeetingIdMessage(meetingId);
        }
        catch (MeetingServiceException mse) {
            throw new MessageHandlerException(CreateMeetingMessageHandler.class,
            "Caught MeetingServiceException", mse);
        }
    }
}

Now review the configuration file located at prj.dir/server/config/smfw/MessageHandlerConfiguration.xml where we associate the CreateMeetingMessage with the CreateMeetingMessageHandler.

Implement a Web Service Client

Now that the Web service is ready, we need some client code to call it. The starter code supplies a client with a blank main() method. Insert the following code into the main() method in order to call the Web service. The client is located at prj.dir/client/soap-client/src/org/calendarapp/soapclient/SoapClient.java.

SoapClient.java
    public static void main(String argv[]) throws Exception {

        // Get the URL for the meeting service
        ClientConfiguration config = (ClientConfiguration)
            Config.getInstance().fetchConfiguration(clientConfigName);
        String url = config.getMeetingServiceUrl();

        // Create a MessageContext (set MessageHandlerFactory to null)
        MessageContext messageContext = new MessageContext(null);

        // Create a MessageClient
        MessageReader messageReader = new MessageReaderImpl();
        MessageWriter messageWriter = new MessageWriterImpl();
        MessageClient messageClient =
            new MessageClient(url, messageContext, messageReader, messageWriter);

        // Create a meeting
        Meeting newMeeting = createNewMeeting();
        log.info("\nCreating a meeting...\n" + newMeeting);
        Message response = messageClient.sendMessage(
            new CreateMeetingMessage(createNewMeeting()));
        logResponse(messageWriter, response);
        String meetingId = ((MeetingIdMessage)response).getMeetingId();
        log.info("\nMeeting #" + meetingId + " created");
    }

Here's an explanation of this code.

  • We first get the URL of the Web service using the ClientConfiguration object. We use Carbon's Configuration service to get this information from the configuration file located at prj.dir/client/config/client/soap-client-config.xml.
  • We then create a MessageContext, setting its MessageHandlerFactory to null. Since we are on the client side, MessageHandlers are not needed.
  • Now we create a new MessageClient giving it the Web service URL, the MessageContext, a MessageReader and a MessageWriter.
  • Once we have the MessageClient, we can use it to send any message to the Web service. In the code shown above, we send a CreateMeetingMessage to the Web service and receive a MeetingIdMessage in response. The received meetingId is then logged.

Test the Web Service

We are now ready to test the Web service.

  1. Open a command shell and change the current directory to prj.dir
  2. .
  3. Execute the following command to build the Calendar application:
    ant build
  4. Execute the following command to start the Web service in Tomcat:
    ant start-soap-server
  5. Open a Web browser and point it to http://localhost:5001/calendarapp
  6. Click on the MeetingService link to see the WSDL. This is the mechanism used by a Web service to publish its WSDL.
  7. Now open another command shell and change the current directory to prj.dir
  8. .
  9. Execute the following command to start the Web service client:
    ant start-soap-client

If you see the following output your Web service is working as expected.

[java] Creating a meeting...

[java] meetingId: null
[java] subject: Project kickoff
[java] location: Room 203
[java] startTime: 07-14-2003 04:58:33
[java] endTime: 07-14-2003 04:58:33
[java] organizer: jdoe
[java] body:
[java] Let's get the ball rolling!
[java] attendees:
[java] jmagic, isRequired=false, status=not_responded
[java] phead, isRequired=true, status=not_responded
[java] thacker, isRequired=false, status=not_responded
[java] jdoe, isRequired=true, status=accepted

[java] Received response of type org.calendarapp.message.MeetingIdMessage
[java] <?xml version="1.0" encoding='UTF-8'?>

[java] <message xsi:type="MeetingIdMessage"
           xmlns="http://www.calendarapp.org/meeting-service"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
[java]   <meeting-id>1</meeting-id>
[java] </message>

[java] Meeting #1 created

Implement the getMeeting() Method

Repeat the process discussed above to expose the getMeeting() method of the MeetingService API. Use the steps shown below to guide you through this exercise. If you get stuck look at the Meeting Sevice Demo for ideas.

  1. Define the request and response messages for the getMeeting() method.
  2. Modify the WSDL document to publish these messages.
  3. Enhance the MessageReader and MessageWriter implementations so that they recognize your new messages
  4. Implement a message handler for your GetMeetingMessage.
  5. Enhance the client application to get the meeting that was created using the CreateMeetingMessage.

Conclusion

In this tutorial we created a Web service by exposing two methods of the MeetingService API. We then accessed these methods from a client application. Hopefully this gives you a good feel for creating and accessing Web services using the Simple Messaging Framework.


Copyright © 2003, Sapient Corporation