Programming Web Services for WebLogic Server
The following sections provide information about the following advanced JWS programming topics:
Typically, client applications use HTTP/S as the connection protocol when invoking a WebLogic Web Service. You can, however, configure a WebLogic Web Service so that client applications use JMS as the transport instead. You configure transports using either JWS annotations or child elements of the jwsc
Ant task, as described in later sections.
When a WebLogic Web Service is configured to use JMS as the connection transport, the endpoint address specified for the corresponding port in the generated WSDL of the Web Service uses jms://
in its URL rather than http://
. An example of a JMS endpoint address is as follows:
jms://myHost:7001/transports/JMSTransport?URI=JMSTransportQueue
The URI=JMSTransportQueue
section of the URL specifies the JMS queue that has been configured for the JMS transport feature. Although you cannot invoke the Web Service using HTTP, you can view its WSDL using HTTP, which is how the clientgen
is still able to generate JAX-RPC stubs for the Web Service.
For each transport that you specify, WebLogic Server generates an additional port in the WSDL. For this reason, if you want to give client applications a choice of transports they can use when they invoke the Web Service (JMS, HTTP, or HTTPS), you should explicitly add the transports using the appropriate JWS annotations or child elements of jwsc
.
Caution: Using JMS transport is an added-value WebLogic feature; non-WebLogic client applications, such as a.NET client, may not be able to invoke the Web Service using the JMS port.
The following procedure describes how to specify that your Web Service can be invoked using the JMS transport.
It is assumed that you have already created a basic JWS file that implements a Web Service and that you want to configure the Web Service to be invoked using JMS. It is also assumed that you have set up an Ant-based development environment and that you have a working build.xml
file that includes targets for running the jwsc
Ant task and deploying the service. For more information, see Iterative Development of WebLogic Web Services, and Programming the JWS File.
See Create JMS Servers.
See Create JMS Modules.
weblogic.wsee.DefaultQueue
) or specify a different name. If you specify a different JNDI name, you later pass this name to the Web Service itself.See Create Queues.
<WLJmsTransport>
child element to the jwsc
Ant task if you want to override JMS ports from the one you specified in the preceding step.See Using the <WLJmsTransport> Child Element of the jwsc Ant Task for details.
See Invoking a WebLogic Web Service Using JMS Transport for information about updating your client application to invoke the Web Service using JMS transport.
If you know at the time that you program the JWS file that you want client applications to use JMS transport (instead of HTTP/S) to invoke the Web Service, you can use the @WLJmsTransport
to specify the details of the invoke. Later, at build-time, you can override the one in the JWS file and add additional JMS transport specifications, by specifying the <WLJmsTransport>
child element of the jwsc
Ant task, as described in Using the <WLJmsTransport> Child Element of the jwsc Ant Task.
Follow these guidelines when using the @WLJmsTranport
annotation:
@WLJmsTransport
annotation in a JWS file. @WLJmsTransport
annotation, you cannot specify any of the other transport annotations (@WLHttpTransport
or @WLHttpsTransport
.)queue
attribute to specify the JNDI name of the JMS queue you configured earlier in the section. If you want to use the default Web Services queue (weblogic.wsee.DefaultQueue
) then you do not have to specify the queue
attribute.The following example shows a simple JWS file that uses the @WLJmsTransport
annotation, with the relevant code in bold:
package examples.webservices.jmstransport;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import weblogic.jws.WLJmsTransport;
@WebService(name="JMSTransportPortType",
serviceName="JMSTransportService",
targetNamespace="http://example.org")
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
use=SOAPBinding.Use.LITERAL,
parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
// WebLogic-specific JWS annotation that specifies the context path and
// service URI used to build the URI of the Web Service is
// "transports/JMSTransport"
@WLJmsTransport(contextPath="transports", serviceUri="JMSTransport",
queue="JMSTransportQueue", portName="JMSTransportServicePort")
/**
* This JWS file forms the basis of simple Java-class implemented WebLogic
* Web Service with a single operation: sayHello
*
* @author Copyright (c) 2005 by BEA Systems. All rights reserved.
*/
public class JMSTransportImpl {
@WebMethod()
public String sayHello(String message) {
System.out.println("sayHello:" + message);
return "Here is the message: '" + message + "'";
}
}
You can also specify the JMS transport at build-time by using the <WLJmsTransport>
child element of the <jws>
element of the jwsc
Ant task. Reasons for specifying the transport at build-time include:
@WLXXXTransport
annotation; thus by default the HTTP transport is used, but at build-time you decide you want to clients to use the JMS transport to invoke the Web Service.If you specify a transport to the jwsc
Ant task, it takes precedence over any transport annotation in the JWS file.
The following example shows how to specify a transport to the jwsc
Ant task:
<target name="build-service">
<jwsc
srcdir="src"
destdir="${ear-dir}">
<jws file="examples/webservices/jmstransport/JMSTransportImpl.java">
<WLJmsTransport
contextPath="transports"
serviceUri="JMSTransport"
portName="JMSTransportServicePort"
queue="JMSTransportQueue"/>
</jws>
</jwsc>
</target>
The preceding example shows how to specify the same values for the URL and JMS queue as were specified in the JWS file shown in Using the @WLJmsTransport JWS Annotation.
For more information about using the jwsc
Ant task, see jwsc.
You write a client application to invoke a Web Service using JMS transport in the same way as you write one using the HTTP transport; the only difference is that you must ensure that the JMS queue (specified by the @WLJmsTransport
annotation or <WLJmsTransport>
child element of the jwsc
Ant task) and other JMS objects have already been created. See Using JMS Transport: Main Steps for more information.
Although you cannot invoke a JMS-transport-configured Web Service using HTTP, you can view its WSDL using HTTP, which is how the clientgen
Ant task is still able to create the JAX-RPC stubs for the Web Service. For example, the URL for the WSDL of the Web Service shown in this section would be:
http://host:port/transports/JMSTransport?WSDL
However, because the endpoint address in the WSDL of the deployed Web Service uses jms://
instead of http://
, and the address includes the qualifier ?URI=
JMS_QUEUE
, the clientgen
Ant task automatically creates the stubs needed to use the JMS transport when invoking the Web Service, and your client application need not do anything different than normal. An example of a JMS endpoint address is as follows:
jms://host:port/transports/JMSTransport?URI=JMSTransportQueue
For general information about invoking a Web Service, see Invoking Web Services.
When you write a client application that uses the clientgen
-generated JAX-RPC stubs to invoke a Web Service, the default service address URL of the Web Service is the one specified in the <address>
element of the WSDL file argument of the Service
constructor.
Sometimes, however, you might need to override this address, in particular when invoking a WebLogic Web Service that is deployed to a cluster and you want to specify the cluster address or a list of addresses of the managed servers in the cluster. You might also want to use the t3
protocol to invoke the Web Service. To override this service endpoint URL when using JMS transport, use the weblogic.wsee.jaxrpc.WLStub.JMS_TRANSPORT_JNDI_URL
stub property as shown in the following example:
package examples.webservices.jmstransport.client;
import weblogic.wsee.jaxrpc.WLStub;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.Stub;
/**
* This is a simple standalone client application that invokes the
* the <code>sayHello</code> operation of the JMSTransport Web service.
*
* @author Copyright (c) 2004 by BEA Systems. All Rights Reserved.
*/
public class Main {
public static void main(String[] args)
throws ServiceException, RemoteException{
JMSTransportService service = new JMSTransportService_Impl(args[0] + "?WSDL" );
JMSTransportPortType port = service.getJMSTransportServicePort();
Stub stub = (Stub) port;
stub._setProperty(WLStub.JMS_TRANSPORT_JNDI_URL,
try {
"t3://shackell01.amer.bea.com:7001");
String result = null;
result = port.sayHello("Hi there! ");
System.out.println( "Got JMS result: " + result );
} catch (RemoteException e) {
throw e;
}
}
}
Some Web Services need access to the SOAP message, for which you can create SOAP message handlers.
A SOAP message handler provides a mechanism for intercepting the SOAP message in both the request and response of the Web Service. You can create handlers in both the Web Service itself and the client applications that invoke the Web Service.
A simple example of using handlers is to access information in the header part of the SOAP message. You can use the SOAP header to store Web Service specific information and then use handlers to manipulate it.
You can also use SOAP message handlers to improve the performance of your Web Service. After your Web Service has been deployed for a while, you might discover that many consumers invoke it with the same parameters. You could improve the performance of your Web Service by caching the results of popular invokes of the Web Service (assuming the results are static) and immediately returning these results when appropriate, without ever invoking the back-end components that implement the Web Service. You implement this performance improvement by using handlers to check the request SOAP message to see if it contains the popular parameters.
The following table lists the standard JWS annotations that you can use in your JWS file to specify that a Web Service has a handler chain configured; later sections discuss how to use the annotations in more detail. For additional information, see the Web Services MetaData for the Java Platform (JSR-181) specification.
The following table describes the main classes and interfaces of the javax.xml.rpc.handler
API, some of which you use when creating the handler itself. These APIs are discussed in detail in a later section. For additional information about these APIs, see the JAX-RPC 1.1 specification.
The following procedure describes the high-level steps to add SOAP message handlers to your Web Service.
It is assumed that you have already created a basic JWS file that implements a Web Service and that you want to update the Web Service by adding SOAP message handlers and handler chains. It is also assumed that you have set up an Ant-based development environment and that you have a working build.xml
file that includes a target for running the jwsc
Ant task. For more information, see Iterative Development of WebLogic Web Services, and Programming the JWS File.
javax.xml.rpc.handler.GenericHandler
abstract class. For information about creating client-side SOAP message handlers and handler chains, see Creating and Using Client-Side SOAP Message Handlers.
When designing your SOAP message handlers and handler chains, you must decide:
Each handler in a handler chain has one method for handling the request SOAP message and another method for handling the response SOAP message. An ordered group of handlers is referred to as a handler chain. You specify that a Web Service has a handler chain attached to it with one of two JWS annotations: @HandlerChain
or @SOAPMessageHandler
. When to use which is discussed in a later section.
When invoking a Web Service, WebLogic Server executes handlers as follows:
handleRequest()
methods of the handlers in the handler chain are all executed in the order specified by the JWS annotation. Any of these handleRequest()
methods might change the SOAP message request.handleRequest()
method of the last handler in the handler chain executes, WebLogic Server invokes the back-end component that implements the Web Service, passing it the final SOAP message request. For example, assume that you are going to use the @HandlerChain
JWS annotation in your JWS file to specify an external configuration file, and the configuration file defines a handler chain called SimpleChain
that contains three handlers, as shown in the following sample:
<jwshc:handler-config xmlns:jwshc="http://www.bea.com/xml/ns/jws"
xmlns:soap1="http://HandlerInfo.org/Server1"
xmlns:soap2="http://HandlerInfo.org/Server2"
xmlns="http://java.sun.com/xml/ns/j2ee" >
<jwshc:handler-chain>
<jwshc:handler-chain-name>SimpleChain</jwshc:handler-chain-name>
<jwshc:handler>
<handler-name>handlerOne</handler-name>
<handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler1</handler-class>
</jwshc:handler>
<jwshc:handler>
<handler-name>handlerTwo</handler-name>
<handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler2</handler-class>
</jwshc:handler>
<jwshc:handler>
<handler-name>handlerThree</handler-name>
<handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler3</handler-class>
</jwshc:handler>
</jwshc:handler-chain>
</jwshc:handler-config>
The following graphic shows the order in which WebLogic Server executes the handleRequest()
and handleResponse()
methods of each handler.
Figure 7-1 Order of Execution of Handler Methods0
Each SOAP message handler has a separate method to process the request and response SOAP message because the same type of processing typically must happen for the inbound and outbound message. For example, you might design an Encryption handler whose handleRequest()
method decrypts secure data in the SOAP request and handleResponse()
method encrypts the SOAP response.
You can, however, design a handler that process only the SOAP request and does no equivalent processing of the response.
You can also choose not to invoke the next handler in the handler chain and send an immediate response to the client application at any point.
Your SOAP message handler class should extend the javax.rpc.xml.handler.GenericHandler
abstract class, which itself implements the javax.rpc.xml.handler.Handler
interface.
The GenericHandler
class is a convenience abstract class that makes writing handlers easy. This class provides default implementations of the lifecycle methods init()
and destroy()
and the various handleXXX()
methods of the Handler
interface. When you write your handler class, only override those methods that you need to customize as part of your Handler
implementation class.
In particular, the Handler interface contains the following methods that you can implement in your handler class that extends GenericHandler
:
Sometimes you might need to directly view or update the SOAP message from within your handler, in particular when handling attachments, such as image. In this case, use the javax.xml.soap.SOAPMessage
abstract class, which is part of the SOAP With Attachments API for Java 1.1 (SAAJ) specification For details, see Directly Manipulating the SOAP Request and Response Message Using SAAJ.
The following example demonstrates a simple SOAP message handler that prints out the SOAP request and response messages to the WebLogic Server log file:
package examples.webservices.soap_handlers.global_handler;
import javax.xml.namespace.QName;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.GenericHandler;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.rpc.JAXRPCException;
import weblogic.logging.NonCatalogLogger;
/**
* This class implements a handler in the handler chain, used to access the SOAP
* request and response message.
* <p>
* This class extends the <code>javax.xml.rpc.handler.GenericHandler</code>
* abstract classs and simply prints the SOAP request and response messages to
* the server log file before the messages are processed by the backend
* Java class that implements the Web Service itself.
*/
public class ServerHandler1 extends GenericHandler {
private NonCatalogLogger log;
private HandlerInfo handlerInfo;
/**
* Initializes the instance of the handler. Creates a nonCatalogLogger to
* log messages to.
*/
public void init(HandlerInfo hi) {
log = new NonCatalogLogger("WebService-LogHandler");
handlerInfo = hi;
}
/**
* Specifies that the SOAP request message be logged to a log file before the
* message is sent to the Java class that implements the Web Service.
*/
public boolean handleRequest(MessageContext context) {
SOAPMessageContext messageContext = (SOAPMessageContext) context;
System.out.println("** Request: "+messageContext.getMessage().toString());
log.info(messageContext.getMessage().toString());
return true;
}
/**
* Specifies that the SOAP response message be logged to a log file before the
* message is sent back to the client application that invoked the Web
* service.
*/
public boolean handleResponse(MessageContext context) {
SOAPMessageContext messageContext = (SOAPMessageContext) context;
System.out.println("** Response: "+messageContext.getMessage().toString());
log.info(messageContext.getMessage().toString());
return true;
}
/**
* Specifies that a message be logged to the log file if a SOAP fault is
* thrown by the Handler instance.
*/
public boolean handleFault(MessageContext context) {
SOAPMessageContext messageContext = (SOAPMessageContext) context;
System.out.println("** Fault: "+messageContext.getMessage().toString());
log.info(messageContext.getMessage().toString());
return true;
}
public QName[] getHeaders() {
return handlerInfo.getHeaders();
}
}
The Handler.init()
method is called to create an instance of a Handler
object and to enable the instance to initialize itself. Its signature is:
public void init(HandlerInfo config) throws JAXRPCException {}
The HandlerInfo
object contains information about the SOAP message handler, in particular the initialization parameters. Use the HandlerInfo.getHandlerConfig()
method to get the parameters; the method returns a java.util.Map
object that contains name-value pairs.
Implement the init()
method if you need to process the initialization parameters or if you have other initialization tasks to perform.
Sample uses of initialization parameters are to turn debugging on or off, specify the name of a log file to which to write messages or errors, and so on.
The Handler.destroy()
method is called to destroy an instance of a Handler
object. Its signature is:
public void destroy() throws JAXRPCException {}
Implement the destroy()
method to release any resources acquired throughout the handler's lifecycle.
The Handler.getHeaders()
method gets the header blocks that can be processed by this Handler
instance. Its signature is:
public QName[] getHeaders() {}
The Handler.handleRequest()
method is called to intercept a SOAP message request before it is processed by the back-end component. Its signature is:
public boolean handleRequest(MessageContext mc)
throws JAXRPCException,SOAPFaultException {}
Implement this method to perform such tasks as decrypting data in the SOAP message before it is processed by the back-end component, and so on.
The MessageContext
object abstracts the message context processed by the SOAP message handler. The MessageContext
properties allow the handlers in a handler chain to share processing state.
Use the SOAPMessageContext
sub-interface of MessageContext
to get at or update the contents of the SOAP message request. The SOAP message request itself is stored in a javax.xml.soap.SOAPMessage
object. For detailed information on this object, see Directly Manipulating the SOAP Request and Response Message Using SAAJ.
The SOAPMessageContext
class defines two methods for processing the SOAP request:
SOAPMessageContext.getMessage()
returns a javax.xml.soap.SOAPMessage
object that contains the SOAP message request. SOAPMessageContext.setMessage(javax.xml.soap.SOAPMessage)
updates the SOAP message request after you have made changes to it.After you code all the processing of the SOAP request, code one of the following scenarios:
true
. The next handler on the request chain is specified as either the next <handler>
subelement of the <handler-chain>
element in the configuration file specified by the @HandlerChain
annotation, or the next @SOAPMessageHandler
in the array specified by the @SOAPMessageHandlers
annotation. If there are no more handlers in the chain, the method either invokes the back-end component, passing it the final SOAP message request, or invokes the handleResponse()
method of the last handler, depending on how you have configured your Web Service.
false
. Blocking the handler request chain processing implies that the back-end component does not get executed for this invoke of the Web Service. You might want to do this if you have cached the results of certain invokes of the Web Service, and the current invoke is on the list.
Although the handler request chain does not continue processing, WebLogic Server does invoke the handler response chain, starting at the current handler. For example, assume that a handler chain consists of two handlers: handlerA and handlerB, where the handleRequest()
method of handlerA is invoked before that of handlerB. If processing is blocked in handlerA (and thus the handleRequest()
method of handlerB is not invoked), the handler response chain starts at handlerA and the handleRequest()
method of handlerB is not invoked either.
javax.xml.rpc.soap.SOAPFaultException
to indicate a SOAP fault.If the handleRequest()
method throws a SOAPFaultException
, WebLogic Server catches the exception, terminates further processing of the handler request chain, and invokes the handleFault()
method of this handler.
JAXRPCException
for any handler-specific runtime errors. The Handler.handleResponse()
method is called to intercept a SOAP message response after it has been processed by the back-end component, but before it is sent back to the client application that invoked the Web Service. Its signature is:
public boolean handleResponse(MessageContext mc) throws JAXRPCException {}
Implement this method to perform such tasks as encrypting data in the SOAP message before it is sent back to the client application, to further process returned values, and so on.
The MessageContext
object abstracts the message context processed by the SOAP message handler. The MessageContext
properties allow the handlers in a handler chain to share processing state.
Use the SOAPMessageContext
sub-interface of MessageContext
to get at or update the contents of the SOAP message response. The SOAP message response itself is stored in a javax.xml.soap.SOAPMessage
object. See Directly Manipulating the SOAP Request and Response Message Using SAAJ.
The SOAPMessageContext
class defines two methods for processing the SOAP response:
SOAPMessageContext.getMessage()
: returns a javax.xml.soap.SOAPMessage
object that contains the SOAP message response. SOAPMessageContext.setMessage(javax.xml.soap.SOAPMessage)
: updates the SOAP message response after you have made changes to it.After you code all the processing of the SOAP response, code one of the following scenarios:
true
. The next response on the handler chain is specified as either the preceding <handler>
subelement of the <handler-chain>
element in the configuration file specified by the @HandlerChain
annotation, or the preceding @SOAPMessageHandler
in the array specified by the @SOAPMessageHandlers
annotation. (Remember that responses on the handler chain execute in the reverse order that they are specified in the JWS file. See Designing the SOAP Message Handlers and Handler Chains for more information.)
If there are no more handlers in the chain, the method sends the final SOAP message response to the client application that invoked the Web Service.
false
. Blocking the handler response chain processing implies that the remaining handlers on the response chain do not get executed for this invoke of the Web Service and the current SOAP message is sent back to the client application.
JAXRPCException
for any handler specific runtime errors. The Handler.handleFault()
method processes the SOAP faults based on the SOAP message processing model. Its signature is:
public boolean handleFault(MessageContext mc) throws JAXRPCException {}
Implement this method to handle processing of any SOAP faults generated by the handleResponse()
and handleRequest()
methods, as well as faults generated by the back-end component.
The MessageContext
object abstracts the message context processed by the SOAP message handler. The MessageContext
properties allow the handlers in a handler chain to share processing state.
Use the SOAPMessageContext
sub-interface of MessageContext
to get at or update the contents of the SOAP message. The SOAP message itself is stored in a javax.xml.soap.SOAPMessage
object. See Directly Manipulating the SOAP Request and Response Message Using SAAJ.
The SOAPMessageContext
class defines the following two methods for processing the SOAP message:
SOAPMessageContext.getMessage()
: returns a javax.xml.soap.SOAPMessage
object that contains the SOAP message. SOAPMessageContext.setMessage(javax.xml.soap.SOAPMessage)
: updates the SOAP message after you have made changes to it.After you code all the processing of the SOAP fault, do one of the following:
handleFault()
method on the next handler in the handler chain by returning true
.false
. The javax.xml.soap.SOAPMessage
abstract class is part of the SOAP With Attachments API for Java 1.1 (SAAJ) specification. You use the class to manipulate request and response SOAP messages when creating SOAP message handlers. This section describes the basic structure of a SOAPMessage
object and some of the methods you can use to view and update a SOAP message.
A SOAPMessage
object consists of a SOAPPart
object (which contains the actual SOAP XML document) and zero or more attachments.
Refer to the SAAJ Javadocs for the full description of the SOAPMessage
class. For more information on SAAJ, go to http://java.sun.com/xml/saaj/index.html.
The SOAPPart
object contains the XML SOAP document inside of a SOAPEnvelope
object. You use this object to get the actual SOAP headers and body.
The following sample Java code shows how to retrieve the SOAP message from a MessageContext
object, provided by the Handler
class, and get at its parts:
SOAPMessage soapMessage = messageContext.getMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
SOAPBody soapBody = soapEnvelope.getBody();
SOAPHeader soapHeader = soapEnvelope.getHeader();
The javax.xml.soap.AttachmentPart
object contains the optional attachments to the SOAP message. Unlike the rest of a SOAP message, an attachment is not required to be in XML format and can therefore be anything from simple text to an image file.
Caution: If you are going to access a java.awt.Image
attachment from your SOAP message handler, see Manipulating Image Attachments in a SOAP Message Handler for important information.
Use the following methods of the SOAPMessage
class to manipulate the attachments:
countAttachments()
: returns the number of attachments in this SOAP message.getAttachments()
: retrieves all the attachments (as AttachmentPart
objects) into an Iterator
object.createAttachmentPart()
: create an AttachmentPart
object from another type of Object
.addAttachmentPart()
: adds an AttachmentPart
object, after it has been created, to the SOAPMessage
.It is assumed in this section that you are creating a SOAP message handler that accesses a java.awt.Image
attachment and that the Image
has been sent from a client application that uses the client JAX-RPC stubs generated by the clientgen
Ant task.
In the client code generated by the clientgen
Ant task, a java.awt.Image
attachment is sent to the invoked WebLogic Web Service with a MIME type of text/xml
rather than image/gif
, and the image is serialized into a stream of integers that represents the image. In particular, the client code serializes the image using the following format:
This means that, in your SOAP message handler that manipulates the received Image attachment, you must deserialize this stream of data to then re-create the original image.
There are two standard annotations you can use in your JWS file to configure a handler chain for a Web Service: @javax.jws.HandlerChain
and @javax.jws.soap.SOAPMessageHandlers
.
When you use the @javax.jws.HandlerChain
annotation (also called @HandlerChain
in this chapter for simplicity) you use the file
attribute to specify an external file that contains the configuration of the handler chain you want to associate with the Web Service. The configuration includes the list of handlers in the chain, the order in which they execute, the initialization parameters, and so on.
Use the @HandlerChain
annotation, rather than the @SOAPMessageHandlers
annotation, in your JWS file if one or more of the following conditions apply:
The following JWS file shows an example of using the @HandlerChain
annotation; the relevant Java code is shown in bold:
package examples.webservices.soap_handlers.global_handler;
import java.io.Serializable;
import javax.jws.HandlerChain;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;
import weblogic.jws.WLHttpTransport;
@WebService(serviceName="HandlerChainService",
name="HandlerChainPortType")
// Standard JWS annotation that specifies that the handler chain called
// "SimpleChain", configured in the HandlerConfig.xml file, should fire
// each time an operation of the Web Service is invoked.
@HandlerChain(file="HandlerConfig.xml", name="SimpleChain")
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
use=SOAPBinding.Use.LITERAL,
parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
@WLHttpTransport(contextPath="HandlerChain", serviceUri="HandlerChain",
portName="HandlerChainServicePort")
/**
* This JWS file forms the basis of simple Java-class implemented WebLogic
* Web Service with a single operation: sayHello. The Web Service also
* has a handler chain associated with it, as specified by the
* @HandlerChain annotation.
* <p>
* @author Copyright (c) 2005 by BEA Systems, Inc. All Rights Reserved.
*/
public class HandlerChainImpl {
public String sayHello(String input) {
weblogic.utils.Debug.say( "in backend component. input:" +input );
return "'" + input + "' to you too!";
}
}
Before you use the @HandlerChain
annotation, you must import it into your JWS file, as shown in the preceding example.
Use the file
attribute of the @HandlerChain
annotation to specify the name of the external file that contains configuration information for the handler chain. The value of this attribute is a URL, which may be relative or absolute. Relative URLs are relative to the location of the JWS file at the time you run the jwsc
Ant task to compile the file.
Use the name
attribute to specify the name of the handler chain in the configuration file that you want to associate with the Web Service. The value of this attribute corresponds to the name
attribute of the <handler-chain>
element in the configuration file.
Warning: It is an error to specify more than one @HandlerChain
annotation in a single JWS file. It is also an error to combine the @HandlerChain
annotation with the @SOAPMessageHandlers
annotation.
For details about creating the external configuration file, see Creating the Handler Chain Configuration File.
For additional detailed information about the standard JWS annotations discussed in this section, see the Web Services Metadata for the Java Platform specification.
When you use the @javax.jws.soap.SOAPMessageHandlers
(also called @SOAPMessageHandlers
in this section for simplicity) annotation, you specify, within the JWS file itself, an array of SOAP message handlers (specified with the @SOAPMessageHandler
annotation) that execute before and after the operations of a Web Service. The @SOAPMessageHandler
annotation includes attributes to specify the class name of the handler, the initialization parameters, list of SOAP headers processed by the handler, and so on. Because you specify the list of handlers within the JWS file itself, the configuration of the handler chain is embedded within the Web Service.
Use the @SOAPMessageHandlers
annotation if one or more of the following conditions apply:
The following JWS file shows a simple example of using the @SOAPMessageHandlers
annotation; the relevant Java code is shown in bold:
package examples.webservices.soap_handlers.simple;
import java.io.Serializable;
import javax.jws.soap.SOAPMessageHandlers;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPMessageHandler;
import javax.jws.WebService;
import javax.jws.WebMethod;
import weblogic.jws.WLHttpTransport;
@WebService(name="SimpleChainPortType",
serviceName="SimpleChainService")
// Standard JWS annotation that specifies a list of SOAP message handlers
// that exeucte before and after an invocation of all operations in the
// Web Serice.
@SOAPMessageHandlers ( {
@SOAPMessageHandler (
className="examples.webservices.soap_handlers.simple.ServerHandler1"),
@SOAPMessageHandler (
className="examples.webservices.soap_handlers.simple.ServerHandler2")
} )
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
use=SOAPBinding.Use.LITERAL,
parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
@WLHttpTransport(contextPath="SimpleChain", serviceUri="SimpleChain",
portName="SimpleChainServicePort")
/**
* This JWS file forms the basis of simple Java-class implemented WebLogic
* Web Service with a single operation: sayHello. The Web Service also
* has a handler chain associated with it, as specified by the
* @SOAPMessageHandler/s annotations.
* <p>
* @author Copyright (c) 2005 by BEA Systems, Inc. All Rights Reserved.
*/
public class SimpleChainImpl {
// by default all public methods are exposed as operations
public String sayHello(String input) {
weblogic.utils.Debug.say( "in backend component. input:" +input );
return "'" + input + "' to you too!";
}
}
Before you use the @SOAPMessageHandlers
and @SOAPMessageHandler
annotations, you must import them into your JWS file, as shown in the preceding example. Note that these annotations are in the javax.jws.soap
package.
The order in which you list the handlers (using the @SOAPMessageHandler
annotation) in the @SOAPMessageHandlers
array specifies the order in which the handlers execute: in forward order before the operation, and in reverse order after the operation. The preceding example configures two handlers in the handler chain, whose class names are examples.webservices.soap_handlers.simple.ServerHandler1
and examples.webservices.soap_handlers.simple.ServerHandler2
.
Use the initParams
attribute of @SOAPMessageHandler
to specify an array of initialization parameters expected by a particular handler. Use the @InitParam
standard JWS annotation to specify the name/value pairs, as shown in the following example:
@SOAPMessageHandler(
className = "examples.webservices.soap_handlers.simple.ServerHandler1",
initParams = { @InitParam(name="logCategory", value="MyService")}
)
The @SOAPMessageHandler
annotation also includes the roles
attribute for listing the SOAP roles implemented by the handler, and the headers
attribute for listing the SOAP headers processed by the handler.
Warning: It is an error to combine the @SOAPMessageHandlers
annotation with the @HandlerChain
annotation.
For additional detailed information about the standard JWS annotations discussed in this section, see the Web Services Metadata for the Java Platform specification.
If you decide to use the @HandlerChain
annotation in your JWS file to associate a handler chain with a Web Service, you must create an external configuration file that specifies the list of handlers in the handler chain, the order in which they execute, the initialization parameters, and so on.
Because this file is external to the JWS file, you can configure multiple Web Services to use this single configuration file to standardize the handler configuration file for all Web Services in your enterprise. Additionally, you can change the configuration of the handler chains without needing to recompile all your Web Services. Finally, if you include handlers in your handler chain that use a non-SOAP transport, then you are required to use the @HandlerChain
annotation rather than the @SOAPMessageHandler
annotation.
The configuration file uses XML to list one or more handler chains, as shown in the following simple example:
<jwshc:handler-config xmlns:jwshc="http://www.bea.com/xml/ns/jws"
xmlns:soap1="http://HandlerInfo.org/Server1"
xmlns:soap2="http://HandlerInfo.org/Server2"
xmlns="http://java.sun.com/xml/ns/j2ee" >
<jwshc:handler-chain>
<jwshc:handler-chain-name>SimpleChain</jwshc:handler-chain-name>
<jwshc:handler>
<handler-name>handler1</handler-name>
<handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler1</handler-class>
</jwshc:handler>
<jwshc:handler>
<handler-name>handler2</handler-name>
<handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler2</handler-class>
</jwshc:handler>
</jwshc:handler-chain>
</jwshc:handler-config>
In the example, the handler chain called SimpleChain
contains two handlers: handler1
and handler2
, implemented with the class names specified with the <handler-class>
element. The two handlers execute in forward order before the relevant Web Service operation executes, and in reverse order after the operation executes.
Use the <init-param>
, <soap-role>
, and <soap-header>
child elements of the <handler>
element to specify the handler initialization parameters, SOAP roles implemented by the handler, and SOAP headers processed by the handler, respectively.
For the XML Schema that defines the external configuration file, additional information about creating it, and additional examples, see the Web Services Metadata for the Java Platform specification.
It is assumed in this section that you have a working build.xml
Ant file that compiles and builds your Web Service, and you want to update the build file to include handler chain. See Iterative Development of WebLogic Web Services, for information on creating this build.xml
file.
Follow these guidelines to update your development environment to include message handler compilation and building:
@HandlerChain
or @SOAPMessageHandlers
annotation, you must rerun the jwsc
Ant task to recompile the JWS file and generate a new Web Service. This is true anytime you make a change to an annotation in the JWS file.If you used the @HandlerChain
annotation in your JWS file, reran the jwsc
Ant task to regenerate the Web Service, and subsequently changed only the external configuration file, you do not need to rerun jwsc
for the second change to take affect.
jwsc
Ant task compiles SOAP message handler Java files into handler classes (and then packages them into the generated application) if all the following conditions are true:@HandlerChain
or @SOAPMessageHandler(s)
annotations of the JWS file.sourcepath
attribute.If you want to compile the handler classes yourself, rather than let jwsc
compile them automatically, ensure that the compiled classes are in your CLASSPATH before you run the jwsc
Ant task.