Java Web services for various client types

Use attachments from Java, .Net, and browser clients for FOP Web services

Successful deployment of Java-based Web services requires detailed knowledge and understanding of fundamental concepts behind Web services, different Simple Object Access Protocol (SOAP) implementations, XML-related technologies, SOAP Fault monitoring, and finally, clients using the Web service.

In this article, I discuss Java-based Web services' design and code for different client types. I cover Axis and .Net implementations and briefly discuss the architecture of both implementations. You should already be familiar with Apache Struts.

Note: You can download this article's source code from Resources.

FOP Web services

Apache's Formatting Objects Processor (FOP) is a print formatter powered by Extensible Stylesheet Language formatting objects (XSL-FO) and an output independent formatter. FOP is a Java application that reads a formatting object tree and renders the resulting pages to a specified output. XSL FOP supports PDF, PCL, PS, SVG, XML, Print, AWT, MIF, and TXT output formats. Browser-, Java-, or .Net-based clients send attachments (as static XSL-FO documents or XML and XSL documents) to an FOP Web service, which renders inputs and responds to the user in the desired output format (e.g., PDF). These attachments are part of a SOAP message. The SOAP standard and most of its Java implementations support MIME (Multipurpose Internet Mail Extensions) attachments. Microsoft's .Net platform supports DIME (Direct Internet Message Encapsulation) attachments only. Apache's Axis SOAP implementation supports MIME as well as DIME attachments. The FOP Web service described in this article covers interoperability issues between Apache Axis for Java and Web Services Enhancements (WSE) 1.0 for Microsoft .Net. First, here's an FOP Web services overview.

FOP Web services are based on the Java platform and use Apache Axis as the SOAP engine. You can install Axis on Java-based Web servers, such as Apache Tomcat, IBM WebSphere, etc. The .Net client uses Microsoft's WSE implementation, and custom filters handle exceptions and SOAP Fault elements. The FOP Web services implementation uses Axis's custom handlers to process attachments prior to invoking XSL-FOP logic and processes responses that might contain SOAP Faults. The custom filters and handlers let you scale the Web services and reuse SOAP Faults and attachment-processing logic. Axis lets you wrap Java exceptions with SOAP Faults. I discuss Axis custom handlers and WSE custom filters later in the article.

Browser-, Java-, and .Net-based clients can invoke FOP Web services. Figure 1 displays an FOP Web service and its .Net (C#, Visual Basic, etc.) client environment. Figure 2 shows an FOP Web service with browser- and Java-based clients. These figures illustrate key differences in how clients invoke FOP Web services. The .Net client directly invokes FOP Web services. The browser-based client invokes FOP Web services using JavaServer Pages (JSP), Struts, Façade, and FOPClient. The Java client invokes FOP Web services using Façade and FOPClient.

The .Net client (e.g., user) invokes a Windows program, FOPClient.exe, which in turn reads attachments from a local directory. The browser-based client also reads attachments from a local directory and then invokes a URL for the FOP Web service. The attachments are inputs to the FOP Web services' FOPService class and are rendered to the XSL-FO processor to perform transformation to the desired output format. The FOPService class then sends a response message to the client. The response message can be a SOAP Fault or attachment (e.g., PDF) that you can store in a local directory.

Figure 1. .Net client FOP Web service. Click on thumbnail to view full-size image.
Figure 2. Browser (with Struts integration) and Java client FOP Web service. Click on thumbnail to view full-size image.

Apache Axis architecture overview

In this section, I briefly discuss how the Axis engine works. Axis's primary responsibility is to invoke a series of handlers and process SOAP messages. Axis uses Message objects to wrap SOAP request, response, and fault messages. These Message objects are placed into MessageContext objects, and become available to all Axis implementation components. So the MessageContext object is a container for request, response, and fault messages and also offers other information, such as target service name, transport protocol for messages, and request message type (e.g., RPC (remote procedural call)/document). The MessageContext object's structure includes a request message and/or response message. Each message has a SOAPPart object and an optional Attachments object (they are Axis APIs). An FOP Web service includes the Attachments object.

The handlers are invoked in order, which is primarily determined by deployment configuration (server-config.wsdd). I will discuss Axis deployment configuration later. A MessageContext object passes through a configured set of handlers; each handler does whatever the MessageContext object requires. An FOP Web service includes a Handler(AttachmentHandler) that processes attachments included in the incoming request message and a Handler(SOAPFaultHandler) that processes SOAP Faults included in the response message. Figure 3 illustrates the Axis architecture.

Figure 3. Axis architecture and SOAP message processing. Click on thumbnail to view full-size image.

Microsoft .Net WSE architecture overview

FOP Web services implementation supports .Net clients by using Microsoft's WSE. WSE represents a subset of Microsoft's GXA (Global XML Architecture) and extends to standard SOAP functionalities. WSE includes:

  • WS-Security: Implements security requirements for Web services.
  • WS-Routing: SOAP-based protocol that routes SOAP packets from one point to another over different types of transport protocols, such as HTTP, TCP, asynchronous, etc.
  • WS-Referral: The WS-Referral protocol provides instructions about how you should route SOAP messages.
  • WS-Attachment: Lets you attach files, such as images, XML, etc., to a SOAP message without serializing its contents into XML. Examples include sending files such as images, XML, etc. At present, .Net implementation supports DIME attachments only, which creates interoperability issues between Java and .Net platforms. WSE uses DIME for sending and receiving SOAP messages with additional attachments, like binary files and XML fragments. DIME encapsulates a SOAP message and its related attachments in a MIME-like way. As with SOAP, you send DIME messages using standard transport protocols such as HTTP, TCP, and UDP. In FOP Web services, you use DIME attachments to send XML and XSL or FO files to the FOPService class.
  • WSE and filters (standard and custom): WSE provides standard sets of classes (under the Microsoft.Web.Services namespace) to implement the above functionalities. WSE includes a standard set of filters and allows custom filters to provide additional functionalities, such as managing SOAP Faults or encrypting and decrypting SOAP request and response messages. Standard and custom filters intercept SOAP request and response messages. WSE's built-in outgoing and incoming standard filter sets provide functionality for diagnostic, security, timestamp, referral, and routing features.

Figure 4 illustrates two custom filters, SOAPFaultOutputFilter and SOAPFaultInputFilter. The SOAPFaultOutputFilter class intercepts and processes SOAP Faults related to request messages and sends them to the Windows Event Log facility. Similarly, SOAPFaultInputFilter processes SOAP Faults related to response messages and sends them to the Windows Event Log facility. The custom filters derive from the SOAPOutputFilter (for request messages) and the SOAPInputFilter (for response messages) classes. You must add these filters to the PipeLine (Microsoft.Web.Services.PipeLine) class and must override ProcessMessage() methods of the SOAPOutputFilter and SOAPInputFilter classes. I'll show you code to implement custom filters later.

Figure 4. Microsoft's .Net WSE and filters (standard and custom). Click on thumbnail to view full-size image.

Java FOP Web services components

This section details FOP Web services' design and code. I start with high-level component diagrams and descriptions and then drill down to lower level class diagrams and descriptions. Later in the article, I cover how .Net clients invoke FOP Web services and handle response messages.

Table 1 shows FOP Web services' server-side components.

Table 1. FOP Web services' components and functionalities. Click on thumbnail to view full-size table.

Figure 5 displays the component diagram.

Figure 5. FOP Web services component diagram

Client component classes

Table 2 and Figure 6 show the client component and related classes.

Table 2. Client component classes and functionalities. Click on thumbnail to view full-size table.
Figure 6. Client component class diagram. Click on thumbnail to view full-size image.

Service component, subcomponents, and classes

Table 3 shows the service components, subcomponents, classes, and functionalities.

Table 3. Service component, subcomponents, classes, and functionalities. Click on thumbnail to view full-size table.

Figure 7 provides a component diagram.

Figure 7. Service component diagram

util component and classes

Table 4 shows the util component, and Figure 8 displays the util component class diagram.

Table 4. util component, classes, and functionalities. Click on thumbnail to view full-size table.
Figure 8. util component class diagram. Click on thumbnail to view full-size image.

Handler component and classes

Table 5 lists handler components.

Table 5. Handler component classes and functionalities. Click on thumbnail to view full-size table.

Figure 9 illustrates handler component classes.

Figure 9. Handler component class diagram

AttachmentHandler

Axis provides provisions to include custom handlers for plug-in custom functionality and make service implementation code scalable and reusable. For FOP Web services, you can implement the custom handler AttachmentHandler. The AttachmentHandler intercepts a SOAP request message from the MessageContext object. AttachmentHandler is a reusable component.

AttachmentHandler sample code

The following code sets properties in the MessageContext object. The FOPService class then accesses these properties (Axis AttachmentPart, filenames related to attachments, and number of attachments) to perform FOP transformation:

AttachmentPart attachments[] = getMessageAttachments(messageContext);
messageContext.setProperty("Attachments",attachments);
Message requestMessage = messageContext.getRequestMessage()
int attachmentCount = requestMessage.countAttachments();
String[] fileNames = getFileNamesofAttachments(attachments,attachmentCount);
messageContext.setProperty("File Names",fileNames);
String cnt = java.lang.String.valueOf(attachmentCount);
messageContext.setProperty("AttachmentCount",cnt);

FaultHandler

FOP Web services provide an Axis custom handler, the FaultHandler class, which intercepts a SOAP Fault (response) and logs it to a configurable log4j appender. This allows centralized and selective SOAP Fault logging, and is an extremely valuable feature for monitoring and maintaining Web services-based infrastructures. The FaultHandler is a reusable class.

FaultHandler sample code

The following FaultHandler code retrieves SOAP Fault elements (e.g., faultActor, faultString, etc.) from a message and sends them to the log4j appender:

final static Logger logger = Logger.getLogger(foo.com);
public void invoke(MessageContext messageContext) throws AxisFault {
    Message responseMessage = messageContext.getResponseMessage();
    SOAPEnvelope SOAPEnvelope =(SOAPEnvelope) responseMessage.getSOAPEnvelope();
    SOAPBodyElement respBody = SOAPEnvelope .getFirstBody();
    AxisFault af = ((SOAPFault) respBody).getFault();
    String faultString = af.getFaultString();
    String faultActor = af.getFaultActor();
    logger.error(faultString);
    logger.error(faultActor);
}

log4j property file

The following code lists the log4j property file:

log4j.rootCategory=ERROR, LOGFILE
# Set the enterprise logger category
# Rolling file appenders, with maximum size of 10 MB
# Maximum backup copies of log files are 5
log4j.logger.foo.com=DEBUG, LOGFILE
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.RollingFileAppender
log4j.appender.LOGFILE.File=fopwebservice.log
log4j.appender.LOGFILE.maxFileSize=10mb
log4j.appender.LOGFILE.maxBackupIndex=5
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%-5p %d{ISO8601} [%t] -
%m%n
log4j.appender.LOGFILE.Append=true

AttachmentHandler and FaultHandler configuration

This code illustrates the Axis server-config.wsdd file:

<service name="FOPService" provider="java:RPC">
  <requestFlow>
     <handler name="AttachmentHandler"  type="java:foo.com.AttachmentHandler">
     </handler>
  </requestFlow>
  <responseFlow>
     <handler name="FaultHandler"  type="java:foo.com.FaultHandler">
     </handler>
  </responseFlow>
</service>

Service component and classes

Table 6 shows the service component, and Figure 10 displays its class diagram.

Table 6. Service component, classes, and functionalities. Click on thumbnail to view full-size table.
Figure 10. Service component class diagram. Click on thumbnail to view full-size image.
1 2 3 Page
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more