Table of Contents
This chapter describes the basic concepts and components of the handler framework with examples.
JAX-WS Web services provide a plug-in style framework, which is more convenient for the handlers and also improves the runtime system functionality of JEUS 7 web services.
The following are two types of handlers.
Use the following criteria to select a handler.
Use the SOAP handler if the entire SOAP message is needed.
Use the logical handler if only the XML document payload of the SOAP message is needed.
In other cases, web services configure the endpoint class to process messages. In a special case where the Java object is required, the Interceptor class supported by JEUS EJB is used. For more information about the JEUS EJB Interceptor class, refer to "JEUS EJB Guide".
For an outbound message, all logical handlers in the handler chain are processed before SOAP handlers. For an inbound message, all SOAP handlers are processed before logical handlers.
In programming client or service-endpoint interfaces, even though logical handlers are configured before SOAP handlers, all logical handlers are processed before SOAP handlers in creating or calling the services.
This section describes how to organize a handler class and discusses about the MessageContext class.
To organize a handler class, a user creates a class that implements a logical handler or SOAP handler interface.
The following is an example of each handler class.
[Example 7.1] << MyLogicalHandler.java >>
public class MyLogicalHandler implements LogicalHandler<LogicalMessageContext> { public boolean handleMessage(LogicalMessageContext messageContext) { LogicalMessage msg = messageContext.getMessage(); return true; } }
[Example 7.2] << MySOAPHandler.java >>
public class MySOAPHandler implements SOAPHandler<SOAPMessageContext> { public boolean handleMessage(SOAPMessageContext messageContext) { SOAPMessage msg = messageContext.getMessage(); return true; } }
As shown in the previous example, both logical and SOAP handlers implement a handler interface, and the handler interface implements two methods, handlerMessage( ) and handleFault( ).
Each method receives an instance that inherits the MessageContext class as a parameter, and the instance is used to determine whether the message is inbound or outbound. The @PostConstruct and @PreDestroy annotations can be used in a user handler class as shown in the following example.
[Example 7.3] << MyLogicalHandler.java >>
public class MyLogicalHandler implements LogicalHandler<LogicalMessageContext> { @PostConstruct public void methodA() {} @PreDestroy public void methodB() {} }
In the previous MyLogicalHandler class, methodA, declared with the @PostConstruct annotation, is invoked after the handler is created and methodB, declared with the @PreDestroy annotation, is invoked before the handler is destroyed.
This section describes how to attach a user handler to a web service.
To create a web service using a Java class, configure the @HandlerChain annotation in the service endpoint implementation class with the wsgen tool.
[Example 7.4] << MyServiceImpl.java >>
@WebService
@HandlerChain( file="handlers.xml")
public class MyServiceImpl {
...
}
The following is the handlers.xml file that is set as the @HandlerChain annotation in the previous example. A server handler is configured in the metadata file, handlers.xml.
[Example 7.5] << handlers.xml >>
<?xml version="1.0" encoding="UTF-8"?> <jws:handler-chains xmlns:jws="http://java.sun.com/xml/ns/javaee"> <jws:handler-chain> <jws:handler> <jws:handler-class>fromjava.handler.TmaxHandler</jws:handler-class> </jws:handler> </jws:handler-chain> </jws:handler-chains>
To create a web service from WSDL, indirectly embed binding customization into the WSDL document, which is used to create the web service, by using the wsimport tool.
The following is an example of indirectly embedding binding customization into the WSDL document by using an external file.
<bindings xmlns="http://java.sun.com/xml/ns/jaxws">
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
<handler-chain>
<handler>
<handler-class>fromwsdl.handler.TmaxHandler</handler-class>
</handler>
</handler-chain>
</handler-chains>
</bindings>
Note that the <handler-chains> element is added to the binding customization file in this example.
As shown in the following example, multiple <handler-chain> elements can be created inside the <handler-chains> element.
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee"> <handler-chain> <service-name-pattern xmlns:tm="http://tmaxsoft.com"> tm:Tmax*Service </service-name-pattern> <handler>...</handler> </handler-chain> <handler-chain> <port-name-pattern xmlns:tm="http://tmaxsoft.com"> tm:TmaxPort </port-name-pattern> <handler>...</handler> </handler-chain> <handler-chain> <protocol-bindings>##SOAP11_HTTP</protocol-bindings> <handler>...</handler> </handler-chain> </handler-chains>
If multiple <handler-chain> elements are created inside the <handler-chains> element, some attributes such as service name, port name, or protocol can be applied to any handler.
This section shows a simple example of implementing a user SOAP handler, that is used to output the log, and using it for a web service.
The javax.xml.ws.handler.LogicalHandler class, a logical handler class, or the javax.xml.ws.handler.SOAPHandler class, a SOAP handler class, inherits the abstract interface, javax.xml.ws.handler.Handler. A user can create a handler, as needed, by implementing the two classes.
The aforementioned handler class, LoggingHandler, that will be implemented in the example is a class that implements the SOAP handler class, javax.xml.ws.handler.soap.SOAPHandler.
[Example 7.6] << LoggingHandler.java >>
public class LoggingHandler implements SOAPHandler<SOAPMessageContext> { public Set<QName> getHeaders() { return null; } public void close(MessageContext messageContext) { } public boolean handleFault(SOAPMessageContext smc) { return true; } public boolean handleMessage(SOAPMessageContext smc) { Boolean inboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); System.out.println("\n##############################################"); System.out.println("### JAX-WS Webservices examples - handler ###"); System.out.println("##############################################"); if (inboundProperty.booleanValue()) { System.out.println("\nClient message:"); } else { System.out.println("\nServer message:"); } SOAPMessage message = smc.getMessage(); try { message.writeTo(System.out); } catch (Exception e) { e.printStackTrace(); } return true; } }
As shown in the previous example, the handler checks whether the message coming into the handler is coming into the server or going out to the client.
The following is the service block from the example Java class. In the service block, the @HandlerChain annotation is used to set the handler class of the server.
[Example 7.7] << handlers.xml >>
<?xml version="1.0" encoding="UTF-8"?> <handler-chains xmlns="http://java.sun.com/xml/ns/javaee"> <handler-chain> <handler> <handler-class>fromjavahandler.common.LoggingHandler</handler-class> </handler> </handler-chain> </handler-chains>
The following example shows the handlers.xml file, which is
registered as the @HandlerChain annotation.
[Example 7.8] << AddNumbersImpl.java >>
@WebService
@HandlerChain(file = "handlers.xml")
public class AddNumbersImpl {
public int addNumbers(int number1, int number2) {
return number1 + number2;
}
}
The following shows the client block of the example Java class. In the client block, binding user declaration is added when using the wsimport tool to create a client through the WSDL document.
[Example 7.9] << AddNumbersClient.java >>
public class AddNumbersClient { public static void main(String[] args) { AddNumbersImpl port = new AddNumbersImplService().getAddNumbersImplPort(); port.addNumbers(10, 20); } }
The following example shows the binding user declaration.
[Example 7.10] << custom-client.xml >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" wsdlLocation="http://localhost:8088/AddNumbers/addnumbers?wsdl" xmlns="http://java.sun.com/xml/ns/jaxws"> <bindings node="wsdl:definitions" xmlns:jws="http://java.sun.com/xml/ns/javaee"> <jws:handler-chains> <jws:handler-chain> <jws:handler> <jws:handler-class> fromjavahandler.common.LoggingHandler </jws:handler-class> </jws:handler> </jws:handler-chain> </jws:handler-chains> </bindings> </bindings>
This section describes how to execute the handler framework using the implemented classes and other configuration files from previous examples. Other service endpoint interface implementation classes and configuration files are the same as those from the previous examples.
Create a service by configuring the handler framework and deploy it to JEUS by executing the following command.
$ ant build deploy
Once the previous step is completed successfully, build and call the client. Since the client is processed by using the wsimport tool, it can only be built after the service has been deployed.
As shown in the following example, create a service with the configured handler framework and then call it. In the console, the LoggingHandler outputs the service-client message exchanges on both the service and client screens.
$ ant run ... run: [java] ############################################## [java] ### JAX-WS Webservices examples - handler ### [java] ############################################## [java] Client message: [java] <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body><ns2:addNumbers xmlns:ns2="http://server.fromjavahandler/"><arg0>10</arg0> <arg1>20</arg1></ns2:addNumbers></S:Body></S:Envelope> [java] ############################################## [java] ### JAX-WS Webservices examples - handler ### [java] ############################################## [java] Server message: [java] <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Header/><S:Body><ns2:addNumbersResponse xmlns:ns2="http://server.fromjavahandler/"> <return>30</return></ns2:addNumbersResponse></S:Body></S:Envelope> ... BUILD SUCCESSFUL