Tutorial | |
Author: Naresh Bhatia (nbhatia@sapient.com) Created: July 2003 Version: $Revision: 1.1 $ ($Author: nbhatia $ / $Date: 2003/07/21 03:30:50 $)
|
| |
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.
|
| |
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.
|
| |
- If you have not yet installed the Simple Messaging Framework, please do so by following the Installation Guide.
- 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.
- 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 .
- 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 .
- Open a command shell and change the current directory to
prj.dir .
- Execute the following command to build the Calendar application:
ant build
- 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
|
| |
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 .
|
| |
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 .
|
| |
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.
|
| |
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 .
|
| |
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.
|
| |
We are now ready to test the Web service.
- Open a command shell and change the current directory to
prj.dir .
- Execute the following command to build the Calendar application:
ant build
- Execute the following command to start the Web service in Tomcat:
ant start-soap-server
- Open a Web browser and point it to
http://localhost:5001/calendarapp
- Click on the
MeetingService link to see the WSDL. This is the mechanism used by a Web service to publish its WSDL.
- Now open another command shell and change the current directory to
prj.dir .
- 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
|
| |
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.
- Define the request and response messages for the
getMeeting() method.
- Modify the WSDL document to publish these messages.
- Enhance the MessageReader and MessageWriter implementations so that they recognize your new messages
- Implement a message handler for your
GetMeetingMessage .
- Enhance the client application to get the meeting that was created using the
CreateMeetingMessage .
|
| |
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.
|
|