Read on - design issue at the end. I have modified the original soap:header support implementation to allow full flexibility around the header management. The way I have achieve this is by allowing the user to specify the header object lifecycle. The current three lifecycles are:
HeaderLifeCycle.REPLACE: the response's header object will overwrite the
request's one
HeaderLifeCycle.DISCARD: the request's header object is removed from the
list after the call.
HeaderLifeCycle.PERSIST: the request's header stays as is.
A user then do:
binding.setHeader("CAM", cam, HeaderLifeCycle.REPLACE );
binding.setHeader("hdrSession", hdrs, HeaderLifeCycle.DISCARD );
To allow the setHeader() and getHeader() method to work off the binding
(PortType) class I had to add a new extension to the PortType interface
(currently org.apache.axis.client.HeaderSupport) this is all fine for client
side since the HeaderSupport interface is implemented by the abstract Stub,
but doing so, I broke the Impl class since it also implements the PortType.
This being said we will ultimately want access to those two methods on the
server-side but in the mean time (since I am not implementing server support
now) I need a spot to put those two methods. Any idea?
Would bringing back the skeleton be the answer to my problem?
I am attaching the patch and the new files so you can experiment the problem
with the Impl class.
Note: I did not yet rename the Header and Headers classes as was suggested
when I submitted the first implementation of the feature.
All feedback much appreciated.
--
Sylvain
This message may contain privileged and/or confidential information. If you
have received this e-mail in error or are not the intended recipient, you
may not use, copy, disseminate or distribute it; do not open any
attachments, delete it immediately from your system and notify the sender
promptly by e-mail that you have done so. Thank you.
ServiceContext.java
Description: Binary data
HeaderLifeCycle.java
Description: Binary data
HeaderKey.java
Description: Binary data
HeaderSupport.java
Description: Binary data
Headers.java
Description: Binary data
Header.java
Description: Binary data
Index: xml-axis/java/src/org/apache/axis/client/Stub.java
===================================================================
RCS file: /home/cvspublic/xml-axis/java/src/org/apache/axis/client/Stub.java,v
retrieving revision 1.8
diff -r1.8 Stub.java
66a67,68
> import org.apache.axis.serviceContext.*;
> import org.apache.axis.message.SOAPHeaderElement;
74c76
< public abstract class Stub implements javax.xml.rpc.Stub {
---
> public abstract class Stub implements javax.xml.rpc.Stub,
>org.apache.axis.client.HeaderSupport {
92a95,97
> // Support for Header
> private ServiceContext serviceContext = new ServiceContext();
>
258a264,374
>
>
> /**
> * This method returns the ServiceContext object for this binding.
> * @return ServiceContext
> */
> public ServiceContext getServiceContext() {
> return serviceContext;
> }
>
> /**
> * This method allow the user to substitute this ServiceContext object with
>another one.
> * In general this is not required, but is provided in case someone would have
>two binding to the same service
> * and would want to have both binding using the same ServiceContext.
> * @return ServiceContext
> */
> public void setServiceContext(ServiceContext sc) {
> serviceContext = sc;
> }
>
>
> /**
> * This method allows a service consumer to set a SOAP Header object defined by
> * <b>soap:header</b> operation element. Every opertaion refering to this
>soap:header
> * part in their binding will send this object as a SOAP Header. The returned
>object
> * will overwrite the current Service's ServiceContext instance of this part
>object if
> * replace is set to true.
> * @param partName a String that identify the soap:header part
> * @param header an Object that will be sent as a SOAPHeader
> * @param lifeCycle a HeaderLifeCycle that defines the request's object life
>cycle.
> * @return void
> */
> public void setHeader(String partName, Object header, HeaderLifeCycle lifeCycle)
>{
> // Store the roudtrip attribute for this header,
> HeaderKey hk = new HeaderKey(partName);
> hk.setLifeCycle(lifeCycle);
>
> serviceContext.setHeader(hk, header);
> }
>
> /**
> * This method is meant to be used by the service consumer to retreive a
>Service's
> * ServiceContext header object. It returns the current object stored for the
>given part
> * name from the response hash of headers. The object the one returned by the
>service
> * provider for that part. It is null when the header does not exists, which
>means that it
> * has not been returned bu the service provider.
> * @param partName a String that identify the soap:header part
> * @return Object
> */
> public Object getHeader(String partName) {
> return serviceContext.getHeader(partName);
> }
>
> /**
> * This method is meant to be used by the BindingStub to set the requested
>request header onto
> * the Call object just before the call gets invoked.
> * @return SOAPHeaderElement
> */
> public SOAPHeaderElement getHeader(String namespace, String partName) {
>
> return new SOAPHeaderElement(
> namespace,
> partName,
> serviceContext.getRequestHeader( new HeaderKey(partName)) );
> }
>
> /**
> * This method is provided with the soap:header part name and the namespace so
>it can update the
> * Header object stored in the Service's ServiceContext using the one retreived
>in the response
> * @return void
> */
> public void updateHeader(org.apache.axis.client.Call call, String namespace,
>String partName) {
>
> try {
> org.apache.axis.Message response =
>call.getMessageContext().getResponseMessage();
> org.apache.axis.message.SOAPEnvelope env =
>response.getSOAPEnvelope();
>
> if ( env != null ) {
> SOAPHeaderElement header = env.getHeaderByName(namespace, partName,
>true);
>
> if ( header != null ) {
>
> // Retrieve the object from the response
> Object theHeader = header.getObjectValue();
> // Retrieve this header object LifeCycle in the hash of request
>headers.
> HeaderKey currentHeaderKey =
>serviceContext.getRequestHeaderKey(new HeaderKey(partName));
>
> if ( currentHeaderKey != null ) {
>
> if (
>currentHeaderKey.getLifeCycle().equals(HeaderLifeCycle.REPLACE) ) {
> // If the header lifeCycle is set to
>HeaderLifeCycle.REPLACE we replace the
> // header object found for that part in the
>ServiceContext requestHeader Hashtable.
> serviceContext.setRequestHeader(currentHeaderKey,
>theHeader);
>
> } else if (
>currentHeaderKey.getLifeCycle().equals(HeaderLifeCycle.DISCARD) ) {
> // If the header lifeCycle is set to
>HeaderLifeCycle.DISCARD we remove the
> // header object found for that part in the
>ServiceContext requestHeader Hashtable.
> serviceContext.removeRequestHeader(currentHeaderKey);
>
> } else if (
>currentHeaderKey.getLifeCycle().equals(HeaderLifeCycle.PERSIST) ) {
> // If the header lifeCycle is set to
>HeaderLifeCycle.PERSIST we keep the the
> // header object therefore we do nothing.
> }
>
> // In all case the received header object is stored in the
>ServiceContext's
> // responseHeader Hashtable. This could be change to a
>lazyer approach where
> // we would store the object on demand only....
> serviceContext.setResponseHeader(currentHeaderKey,
>theHeader);
> }
> }
> }
> } catch ( Exception e ) { /* Not really sure what to do with this... */ }
> }
Index: xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaInterfaceWriter.java
===================================================================
RCS file:
/home/cvspublic/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaInterfaceWriter.java,v
retrieving revision 1.6
diff -r1.6 JavaInterfaceWriter.java
115c115
< pw.println("public interface " + className + " extends java.rmi.Remote {");
---
> pw.println("public interface " + className + " extends java.rmi.Remote,
>org.apache.axis.client.HeaderSupport {");
Index: xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaStubWriter.java
===================================================================
RCS file:
/home/cvspublic/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaStubWriter.java,v
retrieving revision 1.55
diff -r1.55 JavaStubWriter.java
70a71
> import javax.wsdl.extensions.soap.SOAPHeader;
73a75
> import java.util.Enumeration;
231a234
>
259a263
>
262c266
< if (obj instanceof SOAPBody) {
---
> if ( obj instanceof SOAPBody) {
269d272
< break;
275a279,283
>
> // Take care of this operation's
>header management stuff.
> Headers headers = new Headers();
> headers.prepareHeaders( operation );
>
285c293
< operation, parameters, soapAction, namespace, isRPC);
---
> operation, headers, parameters, soapAction, namespace,
>isRPC);
468a477
> Headers headers,
578a588,595
> // Set the headers
> pw.println();
> Enumeration headersEnum = headers.getRequestHeaders().elements();
> while ( headersEnum.hasMoreElements() ) {
> Header h = (Header)headersEnum.nextElement();
> pw.println(" call.addHeader( getHeader( \"" + namespace + "\",
>\"" + h.getPartName() + "\"));");
> }
>
606a624,632
>
> // Update the headers
> headersEnum = headers.getResponseHeaders().elements();
> while ( headersEnum.hasMoreElements() ) {
> Header h = (Header)headersEnum.nextElement();
> pw.println(" updateHeader( call, \"" + namespace + "\", \"" +
>h.getPartName() + "\");");
> }
>
> pw.println();
