Step 2. Implement a SOAP Protocol Handler and a Logical Handler to use with JAX-WS

Time to complete this step: 25 minutes

Handlers are interceptors that can be easily plugged into the Java API for XML-Based Web Services (JAX-WS) 2.0 runtime environment to do additional processing of inbound and outbound messages.

JAX-WS defines two types of handlers:

  • Protocol Handlers:
    • Are specific to a protocol such as SOAP
    • Can access or change any part of the message, including protocol-specific parts such as the message header
  • Logical handlers:
    • Are protocol-agnostic
    • Cannot change any protocol-specific parts of a message
    • Acts only on the payload of the message

In this step, you will write a SOAP protocol handler and a logical handler for the use with JAX-WS services. You will describe the handlers in a custom bindings file using the JAX-WS Bindings Editor .

You will perform following tasks in this step:

Create a SOAP Protocol handler for JAX-WS Web Service

SOAPLoggingHandler

  1. Create a new Java package com.oracle.ticketsystem.handlers in TroubleTicketSystemWebClient project.
  2. Right-click the com.oracle.ticketsystem.handlers pacakge and select New > Class.
  3. In the New Java Class dialog, enter SOAPLoggingHandler as the class name. To make it a SOAP handler, we need to implement the SOAPHandler interface. Click Add... button and choose the SOAPHandler interface. For generic type, specify javax.xml.ws.handler.soap.SOAPMessageContext.

  4. Click Finish.

This creates the SOAPLoggingHandler class that implements methods from the interface.

  • The handleMessage() method is called for normal processing of inbound and outbound messages.
  • The handleFault() method is called when a message contains a protocol fault.
  • The close() method is called after the completion of message processing by all handlers for each web service invocation, that is, after the completion of a SOAP method exchange pattern (or "MEP").
  • The getHeaders() method returns a set of QNames of header blocks processed by the handler.

  1. To report or log when receiving inbound/outbound messages and any fault, implement a private helper method logToSystemOut() that accepts SOAPMessageContext argument.
  2. In the logToSystemOut() method retrieve the value of MessageContext.MESSAGE_OUTBOUND_PROPERTY from SOAPMessageContext. The value of the MESSAGE_OUTBOUND_PROPERTY indicates the message direction. A value of true means that the message is outbound. A value of false indicates an inbound message. Based on the property value, logToSystemOut() shall print either "Outbound message" or "Inbound message." Also, retrieve the SOAPMessage and print it as shown below.
    
    private void logToSystemOut(SOAPMessageContext context) {
     
     Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    
     if (outboundProperty.booleanValue()) {
      System.out.println("Outbound message:");
     } else {
      System.out.println("Inbound message:");
     }
    
     SOAPMessage message = context.getMessage();
     try {
      message.writeTo(System.out);
      System.out.println("");
     } catch (Exception e) {
      System.out.println("Exception in handler: " + e);
     }
    }  

    Edit the handleMessage() and handleFault() methods to log the messages by calling logToSystemOut() method.

    
    @Override
    public boolean handleFault(SOAPMessageContext context) {
     System.out.println("\n==== SOAPLoggingHandler#handleFault() ====");
     logToSystemOut(context);
     System.out.println("==========================================");
     return true;
    }
    
    @Override
    public boolean handleMessage(SOAPMessageContext context) {
     System.out.println("\n==== SOAPLoggingHandler#handleMessage() ====");
     logToSystemOut(context);
     System.out.println("============================================");
     return true;
    } 
  3. Save the SOAPLoggingHandler class.

Create a Logical handler for JAX-WS Web Service

In this step, you will implement a ProductLogicalHandler, which handles inbound messages and modifies the message payload; i.e. convert the value of the product name node to uppercase.

  1. In the Project Explorer View, right-click the com.oracle.ticketsystem.handlers pacakge and select New > Class.
  2. In the New Java Class dialog, enter ProductLogicalHandler as the class name. To make it a Logical handler, we need to implement the LogicalHandler interface. Click the Add... button and choose the LogicalHandler interface. For generic type, specify javax.xml.ws.handler.LogicalMessageContext.

  3. Click Finish.
  4. This creates the ProductLogicalHandler class that implements methods from the interface.

Perform the following steps in handleMessage() to modify the message payload; i.e. convert the value of product name node to uppercase.

  • Retrieve the value of MessageContext.MESSAGE_OUTBOUND_PROPERTY from LogicalMessageContext. The value of MESSAGE_OUTBOUND_PROPERTY indicates the message direction. A value of true means that the message is outbound. A value of false indicates an inbound message. Ignore further processing, if the message is outbound.
  • Retrieve the LogicalMessage from LogicalMessageContext argument.
  • Retrieve the payload from LogicalMessage. If the payload is of type DOMSource then find the name node using XPath.
  • Convert the value of name node to uppercase.


@Override
public boolean handleMessage(LogicalMessageContext context) {

  Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

  // ignore OUTBOUND requests
  if (outboundProperty.booleanValue()) {
   return true;
  }
 
  // only process INBOUND requests
  LogicalMessage lm = context.getMessage();

  Source payload = lm.getPayload();

  if (payload instanceof DOMSource) {
    DOMSource source = ((DOMSource) payload);

    Node rootNode = source.getNode();

    XPath xpath = XPathFactory.newInstance().newXPath();

    NodeList nodes;
    try {
      nodes = (NodeList) xpath.evaluate("//*", rootNode, XPathConstants.NODESET);
      for (int i = 0; i > nodes.getLength(); i++) {
        Node node = nodes.item(i);
        if (node.getNodeName().equals("ns3:name")) {
          String value = node.getFirstChild().getNodeValue();
          node.getFirstChild().setNodeValue(value.toUpperCase());
        }
      }
    } catch (XPathExpressionException e) {
      e.printStackTrace();
    }

  }
  return true;
} 

  1. Save the ProductLogicalHandler class.

Configure handlers using custom bindings file

In this step, you will describe the handlers in custom bindings file using the JAX-WS Bindings Editor .

  1. Open the productBindings.xml file using the JAX-WS Bindings Editor.
  2. In the Design view of the JAX-WS Bindings Editor, select the Handler Chains node and click the Add a Handler Chain link.

  3. That shows the Handler Chain section. Click the  button and choose SOAP Handler. Enter handler name as SOAPLoggingHandler and specify com.oracle.ticketsystem.handlers.SOAPLoggingHandler as the class name.

  4. Similarly, add the ProductLogicalHandler as a LogicalHandler.

  5. Save the productBindings.xml file.

Re-generate the web service client artifacts for the Product Web Service

Since, you have modified the proudctBindings.xml file with additional JAX-WS handlers, you are required to re-generate the Web Service client artifacts.

  1. Before re-generating web service client JAR for the Product Web Service, remove the TroubleTicketSystemWebClient\WebContent\WEB-INF\lib\ProductWebServiceService.jar file.
  2. Performs similar steps that you performed in Step 1 for creating the Web Service client artifacts for the Product Web Service. Refer to the header "Create the web service client artifacts for the Product Web Service" and continue from there.