As with filters, you may either want to modify the complete message or just modify the body of the message. For either kind of requirement, there are corresponding handler types present in SOAP web service named as SOAPHandler and LogicalHandler.

Below is an example code for each type of handler. Just go through the code for each type and it should be easy to understand. I have kept the code to emphasis the handlers rather than the business logic.

JAX-WS SOAP Web Services Tutorial Series
Introduction to SOAP based Java web services
Monitor web service in Eclipse using TCP/IP monitor
JAX-WS wsimport Ant Task in Eclipse
SOAP based web service using Java SE platform
Generate SOAP web service client using wsimport
JAX-WS RPC vs DOCUMENT style web services
Create and Publish SOAP web service on servlet container
Understanding WSDL structure and elements
SOAP Message Exchange Patterns (MEP)
SwA (Soap With Attachments)
JAX-WS Server side handlers
JAX-WS Client side handlers

Server Side Handlers Example

The following source code shows how to configure JAX-WS handlers on the server side. The handler code shall be executed when receiving the request from client or while sending the response to the client.

On the other hand, client side handlers are executed when the client sends the request and when the client receives the response from server.

StockPrice.java is the web service endpoint interface (SEI)

package com.sample;

import javax.jws.WebService;

@WebService
public interface StockPrice {

public String getStockPrice() throws NumberFormatException;

}

StockPriceImpl.java is the web service implementation bean (SIB)

package com.sample;

import javax.jws.HandlerChain;
import javax.jws.WebService;

@WebService(endpointInterface="com.sample.StockPrice")
@HandlerChain(file = "handler-config.xml")
public class StockPriceImpl implements StockPrice {

	@Override
	public String getStockPrice(){
		return "123";
	}
}

You would have noticed that the SIB, refers to handler-config.xml which is an xml file listing the handlers to be used with the web service.

handler-config.xml is the handler configuration file.

<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">  
   <handler-chain>  
      <handler>  
         <handler-class>com.sample.SOAPHandlerDemo</handler-class>  
      </handler>
      <handler>  
         <handler-class>com.sample.LogicalHandlerDemo</handler-class>  
      </handler>    
   </handler-chain>  
</handler-chains> 

The handler config file refers to two handlers viz. SOAPHandlerDemo and LogicalHandlerDemo which are shown below:

SOAPHandlerDemo.java is a protocol handler which has access to header as well as the body of SOAP message.

package com.sample;

import java.util.Set;

import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

public class SOAPHandlerDemo implements SOAPHandler{

	@Override
	public boolean handleMessage(MessageContext context) {
		System.out.println("SOAPHandler --  handleMessage");
		SOAPMessageContext soapMsgCtx = (SOAPMessageContext)context;
		if((Boolean)soapMsgCtx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) {
			try {
				 SOAPElement element=SOAPFactory.newInstance().createElement("test");
				 element.addChildElement("Password");
				 element.addTextNode("1234");
				 soapMsgCtx.getMessage().getSOAPPart().getEnvelope().addHeader().addChildElement(element);
			} catch (SOAPException e) {
				e.printStackTrace();
			}
		}
		return true;
	}

	@Override
	public boolean handleFault(MessageContext context) {
		System.out.println("SOAPHandler --  handleFault");
		return true;
	}

	@Override
	public void close(MessageContext context) {
		System.out.println("SOAPHandler --  close");
	}

	@Override
	public Set getHeaders() {
		System.out.println("SOAPHandler --  getHeaders");
		return null;
	}
}

LogicalHandlerDemo.java is a message handler which has access only to the body of SOAP message.

package com.sample;

import java.io.ByteArrayOutputStream;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.handler.LogicalHandler;
import javax.xml.ws.handler.LogicalMessageContext;
import javax.xml.ws.handler.MessageContext;

public class LogicalHandlerDemo implements LogicalHandler{

	@Override
	public boolean handleMessage(MessageContext context) {
		System.out.println("LogicalHandler --  handleMessage");
		try {
			LogicalMessageContext logicalMsgCtx = (LogicalMessageContext)context;
			Source source = logicalMsgCtx.getMessage().getPayload();
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			Result result = new StreamResult(baos);
		    Transformer transformer = TransformerFactory.newInstance().newTransformer();
			transformer.transform(source, result);
			System.out.println(baos.toString());
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}
		return true;
	}
	
	@Override
	public boolean handleFault(MessageContext context) {
		System.out.println("LogicalHandler --  handleFault");
		return true;
	}
	
	@Override
	public void close(MessageContext context) {
		System.out.println("LogicalHandler --  close");
		
	}
}

StockServicePublisher.java publishes the web service on given URL and namespace.

package com.sample;

import javax.xml.ws.Endpoint;

import com.sample.StockPriceImpl;

public class StockServicePublisher {

	public static void main(String[] args) {
		
		Endpoint.publish("http://localhost:9999/com.sample",new StockPriceImpl());
	}
}

StockClient.java is the client which consumes the web service. Here we are using port 8080 because the TCP/IP monitor is listening on port 8080. If you are not using any traffic monitor, change the port 8080 to 9999 in the below code.

package com.sample;

import java.io.IOException;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

public class StockClient {

	public static void main(String[] args) throws IOException {
	
		URL url = new URL("http://localhost:8080/com.sample?wsdl");
		QName qname = new QName("http://sample.com/","StockPriceImplService");
		Service service = Service.create(url, qname);
		StockPrice sp = service.getPort(StockPrice.class);
		System.out.println(sp.getStockPrice());
	}	
}

Output:

SOAPHandler — getHeaders
SOAPHandler — handleMessage
LogicalHandler — handleMessage
Stock1
LogicalHandler — handleMessage
123
SOAPHandler — handleMessage
LogicalHandler — close
SOAPHandler — close

The above output on the publisher console clearly shows that:
First the “getHeaders” method of SOAPHandlerDemo is invoked on publishing the web service.
The “handleMessage” method of SOAPHandlerDemo and LogicalHandlerDemo in that order is invoked on receiving a request from client to server.
The “handleMessage” method of LogicalHandlerDemo and SOAPHandlerDemo in that order is invoked on sending the response from server to client.

SOAP Request sent from client to server:

<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:getStockPrice xmlns:ns2="http://sample.com/"><arg0>Stock1</arg0></ns2:getStockPrice></S:Body></S:Envelope>

SOAP Response sent from server to client:

<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Header><test xmlns=""><Password>1234</Password></test></S:Header><S:Body><ns2:getStockPriceResponse xmlns:ns2="http://sample.com/"><return xmlns="">123</return></ns2:getStockPriceResponse></S:Body></S:Envelope>

Important points to remember

  • For a message sent by client to the server, first the LogicalHandler and then SOAPHandlers are executed in the order they appear. When this message reaches server then first the SOAPhandler and then LogicalHandler are executed. You need to configure client side handlers for this.
  • The handler chain passes the control from one handler to another.
  • LogicalHandler can only access the body/payload of the SOAP message whereas SOAPHandler can modify the entire message including the header.
  • For a message being sent by the server to client, first the LogicalHandler and then the SOAPHandlers are executed in the order they are defined. When this message reaches client then first the SOAPhandler and then LogicalHandler are executed. The output of above example code verifies this
  • The MessageContext object (SOAPMessageContext in case of SOAPHandler and LogicalMessageContext in case of LogicalHandler) is used to get access to the header, body or properties of the SOAP message.
  • The SOAPHandler needs to implement javax.xml.ws.handler.soap.SOAPHandler interface and LogicalHandler needs to implement javax.xml.ws.handler.LogicalHandler interface.
  • When writing a SOAPHandler, following three methods need to be overridden:
    public boolean handleMessage(SOAPMessageContext smc)
    public boolean handleFault(SOAPMessageContext smc)
    public void close(MessageContext messageContext)
  • When writing a LogicalHandler, following three methods need to be overridden:
    public boolean handleMessage(LogicalMessageContext context)
    public boolean handleFault(LogicalMessageContext context)
    public void close(MessageContext context)
  • handleMessage() is used for normal processing of the SOAP message.
  • handleFault() is executed when the message contains protocol fault.
  • close() method is called after completion of message processing and is used for cleaning up any resources initiated by the handler.

 

原文链接: http://javaexperience.com/adding-soaphandler-and-logicalhandlers-with-soap/