The XML/SOAP level is the level of message processing between the raw level and the application level (see Message Processing Overview). This level works with SOAP protocols, which create SOAP messages. At this level WSO2 SOA Enablement Server provides SOAP Message Handlers as per JAX-RPC specification. They access the SOAP messages that represent either a Web service request or a response.
SOAP Message Handlers are tied to service endpoint and are used to provide additional SOAP message processing. A typical use of a SOAP message handler is to process the SOAP header blocks as part of the processing. A SOAP header can contain transactional, security, contextual, or user profile information. However, handlers have access to the whole SOAP message, including the SOAP body, so that handlers can be used for such things as encrypting and decrypting data in the body of a SOAP message.
In WSO2 SOA Enablement Server, SOAP messages at the XML/SOAP level follow SOAP standards. This means they conform to the Simple Object Access Protocol (SOAP) 1.1 or 1.2 and SOAP with Attachments specifications, which prescribe the format of messages. With the SOAP with Attachments API for Java (SAAJ) 1.1 and The Java API for XML Messaging (JAXM) 1.1, you can create XML messages that conform to these SOAP standards.
In WSO2 SOA Enablement Server, SOAP protocols (SOAP1.1, SOAP1.2) are represented as JAXM profiles.
When WSO2 SOA Enablement Server receives an incoming raw message, it detects the protocol of the message and uses a ProviderConnection object with the proper profile to create a MessageFactory object, which produces SOAPMessage objects for the given protocol.
In the following code fragment, WSO2 SOA Enablement Server gets an instance of the default message factory that produces messages of the default SOAP protocol and then uses the factory to create a message.
MessageFactory factory = MessageFactory.newInstance(); SOAPMessage message = factory.createMessage();
Creating a MessageFactory instance producing the SOAP 1.2 message is shown in the following code fragment. In addition to the example above, ProviderConnectionFactory is used to obtain WaspProviderConnection, which is further used to create the MessageFactory object that will produce SOAPMessage objects according to the SOAP 1.2 protocol.
ProviderConnectionFactory factory = ProviderConnectionFactory.newInstance(); WaspProviderConnection connection = (WaspProviderConnection)factory.createConnection(); MessageFactory factory = connection.createMessageFactory(WaspProviderConnection.MESSAGE_FACTORY_SOAP12); SOAPMessage request = factory.createMessage();
SOAP message handlers are processing units that provide access to SOAP messages, which may represent either a Web service request or a response. A handler can be used in both the Web service and the client applications that invoke the Web service.
In WSO2 SOA Enablement Server, each handler must implement the javax.xml.rpc.handler.Handler interface in accordance with JAX-RPC specifications. The interface contains the following methods:
boolean handleRequest(MessageContext context)
Called when processing the SOAP request message.
boolean handleResponse(MessageContext context)
Called when processing the SOAP response message.
boolean handleFault(MessageContext context)
Called when processing a SOAP fault.
void init(HandlerInfo config)
Called when handler is initiated
void destroy()
Called when handler is destroyed.
QName[] getHeaders()
Gets the header blocks that can be processed by this handler.
The implementation of the handleRequest(), handleResponse() and handleFault() methods can modify the SOAPMessage, including headers and body elements. The messageContext parameter provides access to the message context that is processed by the handler. Access to the SOAPMessage (an instance of javax.xml.soap.SOAPMessage) is enabled from the SOAPMessageContext sub-interface of MessageContext.
public boolean handleRequest(MessageContext msgCtx) { SOAPMessageContext smctx = (SOAPMessageContext)msgCtx; SOAPMessage message = smctx.getMesage(); ... }
The handleRequest() method performs one of the following actions after handler specific processing of the SOAP request message:
Return true to allow the invocation of the next handler on the handler request chain.
If this handler is the last handler in the chain, the target service endpoint is dispatched.
Return false to indicate blocking of the request handler chain.
The next handler in the chain is not invoked and the target service endpoint is not dispatched. The handler response chain is invoked, starting at the current handler. This handler has responsibility to set the SOAP response message.
Throw the javax.xml.rpc.soap.SOAPFaultException to indicate a SOAP fault.
If the exception is thrown by the handleRequest method, further processing of the request handler chain is terminated and a handler fault chain starting at the current handler is invoked.
Throw the JAXRPCException or any other RuntimeException to indicate any handler specific runtime error.
If the exception is thrown by the handleRequest method, further processing of the request handler chain is terminated and a SOAP fault indicating that the message cannot be processed is generated.
The handleResponse() method performs one of the following actions after handler specific processing of the SOAP response message:
Returns true to indicate invoking next handler of the response handler chain.
Returns false to indicate blocking of the response handler chain.
In this case no other response handlers are invoked.
Throws the JAXRPCException or another RuntimeException to indicate a handler specific runtime error.
If the exception is thrown by the handleResponse method, further processing of the request handler chain is terminated and a SOAP fault that indicates that the message cannot be processed is generated.
The handleFault() method performs SOAP fault-related processing. It performs one of the following actions after handler specific processing of the SOAP fault:
Returns true to indicate continued processing of the fault in the handler chain.
Returns false to indicate blocking of the fault in the handler chain.
Throws the JAXRPCException or another RuntimeException to indicate a handler specific runtime error.
The examples in this section demonstrates how a handler can be used to pass authentication information from the client to the server via the header. The client sets information about its username and password to the call context, the client handler takes this information and puts it in the outgoing SOAP message. On the server side, the server handler extracts the authentication information from the incoming SOAP message header and stores it to the call context.
The SOAP header may look like Example 125.
Example 125. SOAP Header
<?xml version="1.0" encoding="UTF-8"?> <e:Header xmlns:e="http://schemas.xmlsoap.org/soap/envelope/"> <h:authentication xmlns:h="http://wso2.com/xmlauth"> <user-name>User A</user-name> <password>asdf1234</password> </h:authentication> </e:Header>
The client handler is given in Example 126.
Example 126. Client Handler
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.processing.handlers; import org.systinet.wasp.handler.WaspGenericHandler; import org.systinet.wasp.webservice.CallContext; import org.systinet.wasp.webservice.Current; import java.util.Map; import javax.xml.namespace.QName; import javax.xml.rpc.JAXRPCException; import javax.xml.rpc.handler.MessageContext; import javax.xml.rpc.handler.soap.SOAPMessageContext; import javax.xml.soap.Name; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPFactory; import javax.xml.soap.SOAPHeader; import javax.xml.soap.SOAPHeaderElement; public class AuthenticationClientHandler extends WaspGenericHandler { public static final QName AUTH_HEADER = new QName("http://wso2.com/xmlauth", "authentication"); public static final QName USER_NAME = new QName("http://wso2.com/xmlauth", "user-name"); public static final QName PASSWORD = new QName("http://wso2.com/xmlauth", "password"); public static final String USER_NAME_KEY = "user-name"; public static final String PASSWORD_KEY = "password"; public boolean handleOutput(MessageContext context) { try { // get the CallContext CallContext ctx = Current.getCallContext(); Map ctxData = ctx.getContextData(); // read userName and password from the CallContext String userName = (String) ctxData.get(USER_NAME_KEY); String password = (String) ctxData.get(PASSWORD_KEY); // test if userName and password exist if ((userName == null) || (password == null)) { throw new JAXRPCException("username or password null"); } SOAPMessageContext messageContext = (SOAPMessageContext) context; SOAPFactory factory = SOAPFactory.newInstance(); // gets the SOAP header SOAPHeader header = messageContext.getMessage() .getSOAPPart() .getEnvelope() .getHeader(); // adds the authetication header Name name = factory.createName( AUTH_HEADER.getLocalPart(), null, AUTH_HEADER.getNamespaceURI()); SOAPHeaderElement element = header.addHeaderElement(name); SOAPElement userNameElement = element.addChildElement( USER_NAME.getLocalPart(), null, USER_NAME.getNamespaceURI()); userNameElement.addTextNode(userName); SOAPElement passwordElement = element.addChildElement( PASSWORD.getLocalPart(), null, PASSWORD.getNamespaceURI()); passwordElement.addTextNode(password); return true; } catch (Exception e) { throw new JAXRPCException(e); } } public QName[] getHeaders() { return new QName[] { AUTH_HEADER }; } }
The server handler is given in Example 127.
Example 127. Service Handler
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.processing.handlers; import org.systinet.wasp.handler.WaspGenericHandler; import org.systinet.wasp.webservice.CallContext; import org.systinet.wasp.webservice.Current; import java.util.Iterator; import java.util.Map; import javax.xml.namespace.QName; import javax.xml.rpc.JAXRPCException; import javax.xml.rpc.handler.MessageContext; import javax.xml.rpc.handler.soap.SOAPMessageContext; import javax.xml.soap.Name; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPFactory; import javax.xml.soap.SOAPHeader; public class AuthenticationServerHandler extends WaspGenericHandler { public static final QName AUTH_HEADER = new QName("http://wso2.com/xmlauth", "authentication"); public static final QName USER_NAME = new QName("http://wso2.com/xmlauth", "user-name"); public static final QName PASSWORD = new QName("http://wso2.com/xmlauth", "password"); public boolean handleInput(MessageContext context) { try { SOAPMessageContext messageContext = (SOAPMessageContext) context; SOAPFactory factory = SOAPFactory.newInstance(); // gets the SOAP header SOAPHeader header = messageContext.getMessage() .getSOAPPart() .getEnvelope() .getHeader(); //gets the authetication header Name name = factory.createName( AUTH_HEADER.getLocalPart(), null, AUTH_HEADER.getNamespaceURI()); Iterator childs = header.getChildElements(name); SOAPElement element = null; if (childs.hasNext()) { element = (SOAPElement) childs.next(); } if (element == null) { throw new JAXRPCException( "Message does not contain authentication header"); } // reads the userName Name userName = factory.createName( USER_NAME.getLocalPart(), null, USER_NAME.getNamespaceURI()); childs = element.getChildElements(userName); String userNameValue = null; if (childs.hasNext()) { userNameValue = ((SOAPElement) childs.next()).getValue(); } if (userNameValue == null) { throw new JAXRPCException("user-name expected"); } //reads the password Name password = factory.createName( PASSWORD.getLocalPart(), null, PASSWORD.getNamespaceURI()); childs = element.getChildElements(password); String passwordValue = null; if (childs.hasNext()) { passwordValue = ((SOAPElement) childs.next()).getValue(); } if (passwordValue == null) { throw new JAXRPCException("password expected"); } // store it to the CallContext CallContext ctx = Current.getCallContext(); Map ctxData = ctx.getContextData(); ctxData.put(USER_NAME, userNameValue); ctxData.put(PASSWORD, passwordValue); } catch (Exception e) { if (e instanceof JAXRPCException) { throw (JAXRPCException) e; } else { throw new JAXRPCException(e); } } return true; } public QName[] getHeaders() { return new QName[] { AUTH_HEADER }; } }
The examples above manipulate SOAP request and response messages as per the SOAP with Attachments API for Java (SAAJ). SAAJ is an API that provides a tree-like view of SOAP messages.
Instead of using the tree-like SAAJ API, you can access and process SOAP messages in a stream-based manner using the Tokenizer. The tokenizer represents an XML document as a sequence of XML tokens (elements).
Example 128 shows a simple stream-based handler.
Example 128. Stream-Based Handler Using Tokenizer
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.processing.handlers; import org.idoox.xml.Token; import org.idoox.xml.Tokenizer; import org.idoox.xml.TokenizerException; import org.idoox.xml.TokenizerSource; import org.idoox.xml.TokenizerWrapper; import java.io.IOException; import javax.xml.namespace.QName; import javax.xml.rpc.JAXRPCException; import javax.xml.rpc.handler.Handler; import javax.xml.rpc.handler.HandlerInfo; import javax.xml.rpc.handler.MessageContext; import javax.xml.rpc.handler.soap.SOAPMessageContext; import javax.xml.rpc.soap.SOAPFaultException; import javax.xml.soap.SOAPPart; public class LoggingHandler implements Handler { public boolean handleRequest(MessageContext context) throws SOAPFaultException { try { SOAPMessageContext messageContext = (SOAPMessageContext) context; // gets the SOAPPart SOAPPart part = messageContext.getMessage() .getSOAPPart(); // gets the tokenizer source TokenizerSource source = (TokenizerSource) part.getContent(); // create new logging tokenizer is the wrapper of source tokenizer LoggingTokenizer loggingTokenizer = new LoggingTokenizer(source.getTokenizer()); // sets the wrapped tokenizer to source source.setTokenizer(loggingTokenizer); // sets the source to content part.setContent(source); } catch (Exception e) { throw new JAXRPCException(e); } return true; } public boolean handleResponse(MessageContext context) { try { SOAPMessageContext messageContext = (SOAPMessageContext) context; // gets the SOAPPart SOAPPart part = messageContext.getMessage() .getSOAPPart(); // gets the tokenizer source TokenizerSource source = (TokenizerSource) part.getContent(); // create new logging tokenizer is the wrapper of source tokenizer LoggingTokenizer loggingTokenizer = new LoggingTokenizer(source.getTokenizer()); // sets the wrapped tokenizer to source source.setTokenizer(loggingTokenizer); // sets the source to content part.setContent(source); } catch (Exception e) { throw new JAXRPCException(e); } return true; } public boolean handleFault(MessageContext context) { return true; } public void init(HandlerInfo config) { } public void destroy() { } public QName[] getHeaders() { return new QName[0]; } /** * Logging tokenizer. Wrappes original tokenizer * and logs tokens. */ class LoggingTokenizer extends TokenizerWrapper { // current token private Token token = new Token(); // detects the first token private boolean first = true; // counter for intending private int depth = 0; public LoggingTokenizer(Tokenizer tokenizer) { super(tokenizer); } public byte next() throws TokenizerException, IOException { if (first) { // reads the envelope first = false; super.readToken(token); System.out.println(token); } byte next = super.next(); switch (next) { case START_TOKEN: depth++; super.readToken(token); printSpaces(); System.out.println(token); break; case END_TOKEN: depth--; break; } return next; } privatevoid printSpaces() { for (int i = 0; i < depth; i++) { System.out.print(" "); } } } }
A number of clients use the information about headers contained in WSDL. For example, .NET-generated stubs from such WSDL documents contain popper member variables and the attributes needed to deserialize headers correctly. The purpose of this section is to show how to use WSO2 SOA Enablement Server to generate information about headers to WSDL.
The SOAP Message handler consumes and produces SOAP headers. Any number of handlers can be configured for an endpoint and any number of headers can be configured for a handler. The structure and direction of SOAP headers is described in WSDL using the soap:header element in the WSDL soap:binding element. The direction of the header ("in," "out" or "in/out") depends on whether the soap:header element is included in input operation binding, output operation binding or both, respectively.
Every header is specified by a message part. The structure of this message part is described by an XML Schema element or XML Schema type, depending on the SOAP use (literal or encoded, respectively).
Using WSO2 SOA Enablement Server, you have two ways to specify the Schema of a SOAP header. The first method is to specify it directly. The second is to use a Java class, which is then converted to the Schema by the Java2Schema tool. The two methods are equivalent. (Please see Example 129 and Java2Schema).
![]() | Note |
---|---|
Using a Java class to generate a SOAP header schema has nothing to do with Java-level header processing. The Java class is only used as a description of the header. |
You then generate a soap:header in WSDL in one of two ways, depending on how the service is deployed:
For persistently deployed services: Using the Java2WSDL tool, the soap:header is generated when the deployment descriptor is processed.
For services deployed using Runtime Publishing API: Headers must be specified using one of the Handlers.insert() methods (please see Handlers
![]() | Note |
---|---|
WSO2 SOA Enablement Server 6.5.4 performs a second step in generating SOAP headers, updating the headers in WSDL to reflect the configuration at the time of deployment. This is completely automated. WSO2 SOA Enablement Server performs this task in the least intrusive way possible. |
For Java2WSDL to generate headers, you must create a deployment descriptor that describes each handler you are using and its headers. Each description is contained in a <handler> element. Once this is done, run Java2WSDL --deployment-descriptor [name of the deployment descriptor you created] --processing [processing name], and Java2WSDL will automatically generate headers.
As mentioned earlier, you can describe headers within a <handler> element using either XML schema or a Java class. Here we are giving only a few examples. See the Deployment Descriptor Reference for a complete description of the <handler> element.
The following header description, BasicAuth,can be written either as a Java class or as an XML Schema complex type (Example 129):
Example 129. Specifying Schema Directly vs. via Java Class
Java class BasicAuth
public class BasicAuth { public String username; public String password; }
Schema for BasicAuth
<xs:complexType name="BasicAuth"> <xs:sequence> <xs:element name="password" nillable="true" type="xs:string"/> <xs:element name="username" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType>
If you use Java2Schema on the BasicAuth class, you will generate the BasicAuth schema.
Example 130 and Example 131 are derived from the servicepackageclass.xml deployment descriptor. This is a descriptor for the HeaderService, describing BasicAuth either as a Java class or as a schema, within a handler named MyHandler.
Example 130. Deployment Descriptor with Handler Element Describing BasicAuth as Java Class
<?xml version="1.0" encoding="UTF-8"?> <package name="HeadersDemo" targetNamespace="http://wso2.com/package/demo/advanced/headers/server" version="4.6" xmlns="http://wso2.com/wasp/package/1.2" xmlns:tns="http://wso2.com/package/demo/advanced/headers/server" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://wso2.com/wasp/package/1.2 http://wso2.com /wasp/package/1.2"> <service-instance implementation-class="demo.advanced.headers.server.HeadersService" name="HeadersInstance"/> <processing name="HeadersProcessing"> <use ref="tns:MyHandler"/> </processing> <handler direction="in" implementation-class="demo.advanced.headers.server.ServerHandler" name="MyHandler"> <header class="test.BasicAuth" direction="in out" name="ns0:authentication" xmlns:ns0="http://wso2.com/xmlauth"/> </handler> <service-endpoint name="HeadersEndpoint" path="/demo/advanced/HeadersService" processing="tns:HeadersProcessing" service-instance="tns:HeadersInstance"> <wsdl service="wsdlns:JavaService" uri="Definitions_demo_advanced_headers_server.wsdl" xmlns:wsdlns="http://wso2.com/package/demo/advanced/headers/server"/> </service-endpoint> </package>
Example 131. Deployment Descriptor with Handler Element Describing BasicAuth as Schema
<?xml version="1.0" encoding="UTF-8"?> <package name="HeadersDemo" targetNamespace="http://wso2.com/package/demo/advanced/headers/server" version="4.6" xmlns="http://wso2.com/wasp/package/1.2" xmlns:tns="http://wso2.com/package/demo/advanced/headers/server" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://wso2.com/wasp/package/1.2 http://wso2.com /wasp/package/1.2"> <service-instance implementation-class="demo.advanced.headers.server.HeadersService" name="HeadersInstance"/> <processing name="HeadersProcessing"> <use ref="tns:MyHandler"/> </processing> <handler direction="in" implementation-class="demo.advanced.headers.server.ServerHandler" name="MyHandler"> <header direction="in out" name="ns0:authentication" xmlns:ns0="http://wso2.com/xmlauth"/> <schema location="resource:/test/BasicAuth.xsd" namespaceURI="http://wso2.com/xmlauth"/> </handler> <service-endpoint name="HeadersEndpoint" path="/demo/advanced/HeadersService" processing="tns:HeadersProcessing" service-instance="tns:HeadersInstance"> <wsdl service="wsdlns:JavaService" uri="Definitions_demo_advanced_headers_server.wsdl" xmlns:wsdlns="http://wso2.com/package/demo/advanced/headers/server"/> </service-endpoint> </package>
Now have Java2WSDL generate the WSDL file with SOAP headers by using the following command-line:
Java2WSDL --deployment-descriptor servicepackageclass.xml --processing HeadersProcessing test.HeaderService
![]() | Important |
---|---|
You cannot generate headers for the deployment descriptor by using Deploy/Undeploy or WaspPackager to GENERATE WSDL. Instead, you must pass in pre-generated WSDL as an argument. To generate WSDL, use the Java2WSDL Tool. |
Headers can be added with the Runtime API using the following Handler method (see handlers in Runtime Publishing):
int insert(WASPHandlerInfo handlerInfo);
Example 132 shows the use of the Handlers.insert(WASPHandlerInfo) method.
Example 132. Handlers.insert Method
ServiceEndpoint endpoint = ServiceEndpoint.create( SERVICE_PATH, HeaderServiceImpl.class); Handlers handlers = endpoint.getHandlers(); QName header = new QName("http://wso2.com/xmlauth","authentication"); WASPHandlerInfo handlerInfo = WASPHandlerInfo.create( new MyHandler(), new QName[]{header}); handlerInfo.setHeaderSchema(header, test.BasicAuth.class); handlerInfo.setDirection(WASPHandlerInfo.DIRECTION_IN); handlers.insert(handlerInfo);
For more details, consult the Javadoc org.systinet.wasp.webservice.Handlers.
A SOAP message can contain one or more attachments in addition to the SOAP part. An attachment can contain application-specific data such as images. However, there is no restriction on the data type in an attachment, so it can contain data in XML or text format as well.
The SOAPMessage object provides methods for creating AttachmentPart objects and for adding them to a SOAPMessage object. The following code fragment in Example 133 illustrates adding an image file as an attachment to the SOAPMessage object:
Example 133. Adding an Image Attachment to a SOAP Message
SOAPMessage message = messageContext.getMessage(); FileInputStream file = new FileInputStream("image.jpg"); AttachmentPart attachmentPart = message.createAttachmentPart(file, "image/jpeg"); message.addAttachmentPart(attachmentPart);
The following code fragment in Example 134 illustrates accessing an attachment from the SOAPMessage object:
Example 134. Accessing an Attachment to a SOAP Message
SOAPMessage message = messageContext.getMessage(); Iterator iterator = message.getAttachments(); while (iterator.hasNext()) { AttachmentPart attachmentPart = (AttachmentPart) iterator.next(); InputStream stream = (InputStream)attachmentPart.getContent(); FileOutputStream toStream = new FileOutputStream("image.jpg"); byte[] buffer = new byte[1024]; int length; while ((length = stream.read(buffer)) > 0) { toStream.write(buffer, 0, length); } toStream.close(); }
If a message sent by a client fails, the client may get back a response containing a SOAP Fault with information about the error.
SOAP Fault contains the following elements:
Fault code - always required. The default fault codes are:
VersionMismatch - the namespace of SOAP Envelope was invalid.
MustUnderstand - an immediate child element of the SOAP Header element that was either not understood or not obeyed by the processing party contained a SOAP mustUnderstand attribute with a value of "1".
Client - The Client class of errors indicate that the SOAP Message was incorrectly formed or did not contain the appropriate information in order to succeed.
Server - The Server class of errors indicate that the SOAP Message could not be processed for reasons not directly attributable to the contents of the message itself but rather to the processing of the message.
Fault string - Always required. A human readable explanation of the fault.
Fault actor - Carries information about what caused the fault to happen within the message path.
Detail object - Carries information about why the error happened.
In the SAAJ API, a SOAP fault is represented by the SOAPFault object. The SOAPFault object can be added to the SOAP message by any party. For example, when a SOAP message is processed in the SOAP message handler, the javax.xml.rpc.soap.SOAPFaultException can be thrown by the handleRequest method of the handler. In this case, the handler implementation class has the responsibility of setting the SOAP fault in the SOAP message.
The following code fragment shows how a SOAPFault object is added to a SOAPMessage:
SOAPMessage message = messageContext.getMessage(); SOAPBody body = message.getSOAPPart().getEnvelope().getBody(); SOAPFault fault = body.addFault(); fault.setFaultCode("MustUnderstand"); fault.setFaultString("SOAP Must Understand Error");
For an example of an XML/SOAP client using SOAP faults, please see Client Using SOAP Faults.
WSO2 SOA Enablement Server for Java contains support for the final version of SOAP 1.2. This specification can be found at SOAP Version 1.2 Part 1: Messaging Framework and SOAP Version 1.2 Part 2: Adjuncts.
Support of SOAP 1.2 in WSO2 SOA Enablement Server is transparent for users. The user chooses the preferred protocol (or both SOAP 1.1 and SOAP 1.2 protocols) and the service uses it. Java services, JAXM listeners and JAX-RPC handlers benefit from the transparency and process messages regardless if they follow SOAP 1.1 or SOAP 1.2. However, if you want to find out which protocol is currently being used, you can get this information from CallContext(constant CallContext.XML_PROTOCOL) or by calling WaspSOAPMessage.getXMLProtocol().
![]() | Note |
---|---|
Services using SOAP 1.2 support in previous versions of WSO2 SOA Enablement Server are not compatible with services using the current version of WSO2 SOA Enablement Server - these services may not work in the current version. |
Creating a SOAP 1.2 Web service may be done either at runtime or statically, in the deployment descriptor.
When deploying a service at runtime (see the section Runtime Publishing), it is possible to specify which protocol will be used before the service is published. The service can use either one or both of the SOAP protocols.
The service's WSDL determines whether it will use SOAP 1.1, 1.2 or both. If you create the WSDL with only the SOAP 1.2 binding, the service will be accessible only through SOAP 1.2. For runtime-published services, you can generate WSDL using Java2WSDL.generateDefinition. If you do not generate the WSDL document yourself, WSO2 SOA Enablement Server generates it when the service is published. In the latter case, the generated WSDL will contain support for the protocols that you specified as default XML protocols during installation.
This is illustrated in Example 135. A client for this service follows, in Example 136.
Example 135. Runtime Registration of a SOAP 1.2 Service
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.basics.soap12; import example.basics.webservices.HelloServiceImpl; import org.idoox.wasp.tools.java2wsdl.Java2WSDL; import org.idoox.wasp.tools.java2wsdl.Java2WSDLFactory; import org.systinet.wasp.Wasp; import org.systinet.wasp.webservice.Registry; import org.systinet.wasp.webservice.ServiceEndpoint; import javax.wsdl.Definition; public class Hello12Server { public static void main(String[] args) throws Exception { // initialize WASP and start server HTTP server Wasp.startServer("http://localhost:6060"); // publish HelloService on path like '/demo/basic/HelloService' ServiceEndpoint serviceEndpoint = ServiceEndpoint.create( "/demo/basic/Hello12Service", new HelloServiceImpl()); Java2WSDL java2wsdl = Java2WSDLFactory.newJava2WSDL(); //create WSDL with support of both protocols (SOAP 1.1, SOAP 1.2) java2wsdl.setProtocol(Java2WSDL.PROTOCOL_SOAP11_SOAP12); Definition wsdl = java2wsdl.generateDefinition(HelloServiceImpl.class); serviceEndpoint.setWSDL(wsdl); Registry.publish(serviceEndpoint); System.out.println( "HelloService is published on /demo/basic/Hello12Service" + " (accessible through SOAP 1.1 and SOAP 1.2)"); } }
The following code in Example 136, is the client for the service shown in Example 135.
Example 136. SOAP 1.2 Runtime Client
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.basics.soap12; import example.basics.invocation.HelloService; import org.systinet.wasp.soap.WaspSOAPMessage; import org.systinet.wasp.webservice.CallContext; import org.systinet.wasp.webservice.Registry; import org.systinet.wasp.webservice.ServiceClient; import java.util.Map; public class Hello12Client { public static void main(String[] args) throws Exception { // lookup service ServiceClient serviceClient = ServiceClient.create( "http://localhost:6060/demo/basic/Hello12Service/wsdl"); Map callContextData = serviceClient.getCallContext() .getContextData(); // explicitly choose SOAP 1.2 protocol (regardless of default settings) callContextData.put(CallContext.XML_PROTOCOL, WaspSOAPMessage.XML_PROTOCOL_SOAP12); HelloService helloService = (HelloService) serviceClient.createProxy(HelloService.class); // call service and print out a response message from HelloService System.out.println(helloService.hello("world")); } }
As mentioned in the previous section, the protocols a service will use are determined from its WSDL. When generating a WSDL description from a Java class or interface, support of either SOAP 1.1 or SOAP 1.2 or both protocols by adding the --protocol parameter. If you do not specify this parameter, the Java2WSDL tool will use default setting.
For more information, see Starting from Java in Writing WS:Jumpstart.
SOAP 1.2 is an evolutionary update to SOAP 1.1, without many significant changes. The main changes in the protocol itself are:
fault structure changed; many specific fault codes added
actor attribute renamed to role;
SOAP media type changed from text/xml to application/soap+xml, SOAPAction HTTP header moved to action parameter of the media type
support for HTTP method GET added
SOAP Encoding simplified (mostly arrays and references), RPC representation extended
The SOAP With Attachments specification uses a SOAP 1.1 encoding feature that allows linking to data using URIs. This means that a piece of data can be outside the SOAP envelope, for example in a MIME attachment. In SOAP 1.2 Encoding, the references can only point to data inside the same XML document. When a new scheme for referencing attachments is created and accepted by SOAP toolkits, it will be supported in WSO2 SOA Enablement Server as well. Because WSO2 SOA Enablement Server references attachments in SOAP 1.2 messages in the same way as it does in SOAP 1.1 messages, you can use attachments in SOAP 1.2 in WSO2 SOA Enablement Server to WSO2 SOA Enablement Server communication without any problems.
SOAP 1.1 Encoding allowed the serialization of sparse arrays; that is, big arrays that only contain a few items. In SOAP 1.2 Encoding, sparse arrays are considered application-level type (in the same way as containers/collections) and all arrays in SOAP 1.2 Encoding must have all items serialized.
Sparse arrays are very seldom used. They have not been supported in WSO2 SOA Enablement Server for Java since version 4.5.