Did you configureNonBrokenHTTPSender before calling createCall? Make sure you call createCall after the configuring the HTTPSender because it overwrites the service config. I don't know why the registration wouldn't work afterwards in that case. Maybe Axis developers can chime in here?

You could try using the wsdd: open up the class I sent you and search for where it creates the wsdd. Now add typemapping statements to that hardcoded wsdd file. Then try configureNonBrokenHTTPSender and send it the uwsewsdd flag as 'true', it should use the hardcoded wsdd you just edited.

Aaron

Benjamin Flohr wrote:

Tried that but unfortunately it didn't do it for us... Our problem seems to
be that the handler registration, which we do in the generated stub
(call.setClientHandlers( handler, handler );) destroys any reference to previously
registered typemappings in the call. Even if we reregister them they don't
work.... We could try the client side deployment descriptor but don't know where
to put it.....
thanks


Andrew and Benjamin
here's our code:


in this method we set the header, we call this mehtods in all our
service-methods:

 private Call writeHeader( Call call )
    {
        MyHTTPHandler handler = new MyHTTPHandler();

        StringBuffer sb = new StringBuffer();
        String key = this.getKeyedDigest( this.getEnvelopeAsString( call )
);

        //set the header info here
        sb.append("HMAC_KEY: \"" + key + "\"\n" );

handler.setOtherHeaders( sb );

call.setClientHandlers( handler, handler );


return call; }



here the Call is created in the stub:

   private org.apache.axis.client.Call createCall()
            throws java.rmi.RemoteException
    {
        try
        {
            org.apache.axis.client.Call _call = (
org.apache.axis.client.Call ) super.service.createCall();

            if ( super.maintainSessionSet )
            {
                _call.setMaintainSession( super.maintainSession );
            }

            if ( super.cachedUsername != null )
            {
                _call.setUsername( super.cachedUsername );
            }

            if ( super.cachedPassword != null )
            {
                _call.setPassword( super.cachedPassword );
            }

            if ( super.cachedEndpoint != null )
            {
                _call.setTargetEndpointAddress( super.cachedEndpoint );
            }

            if ( super.cachedTimeout != null )
            {
                _call.setTimeout( super.cachedTimeout );
            }

            if ( super.cachedPortName != null )
            {
                _call.setPortName( super.cachedPortName );
            }

java.util.Enumeration keys = super.cachedProperties.keys();

            while ( keys.hasMoreElements() )
            {
                java.lang.String key = ( java.lang.String )
keys.nextElement();
                _call.setProperty( key, super.cachedProperties.get( key ) );
            }

            // All the type mapping information is registered
            // when the first call is made.
            // The type mapping information is actually registered in
            // the TypeMappingRegistry of the service, which
            // is the reason why registration is only needed for the first
call.
            synchronized ( this )
            {
                if ( firstCall() )
                {
                    // must set encoding style before registering
serializers
                    _call.setSOAPVersion(
org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS );
                    _call.setEncodingStyle(
org.apache.axis.Constants.URI_SOAP11_ENC );

                    for ( int i = 0; i < cachedSerFactories.size(); ++i )
                    {
                        java.lang.Class cls = ( java.lang.Class )
cachedSerClasses.get( i );
                        javax.xml.namespace.QName qName = (
javax.xml.namespace.QName ) cachedSerQNames.get( i );
                        java.lang.Class sf = ( java.lang.Class )
cachedSerFactories.get( i );
                        java.lang.Class df = ( java.lang.Class )
cachedDeserFactories.get( i );
                        _call.registerTypeMapping( cls, qName, sf, df, false
);
                    }
                }
            }

            return _call;
        }
        catch ( java.lang.Throwable t )
        {
            throw new org.apache.axis.AxisFault( "Failure trying to get the
Call object",
                    t );
        }
    }




Try this, I edited it in this message to remove some inapplicable things, so your mileage may vary. Just call: myservice = HTTPTransportHelper.configureNonBrokenHTTPTransport(myservice);

Make SURE to edit HANDLER_CLASS field to refer to YOUR HTTPSender class.

There are technically two ways to register the handler: programmatically, and through the client side deployment descriptor. In practice, to my knowledge, nobody uses client side deployment descriptors because they are rather superfluous (you don't really "deploy" clients). The flag usewsdd is there in case you want to test this path.

---------------------------------------

package your.package.name;

import org.apache.axis.Handler;
import org.apache.axis.configuration.XMLStringProvider;
import org.apache.axis.deployment.wsdd.WSDDConstants;

import org.apache.axis.EngineConfiguration;
import org.apache.axis.client.AxisClient;
import org.apache.axis.SimpleTargetedChain;
import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
import org.apache.axis.configuration.SimpleProvider;

public final class HTTPTransportHelper {
private static final Class HANDLER_CLASS = your.package.name.YourHTTPSender.class;


private HTTPTransportHelper() {}

public static org.apache.axis.client.Service configureNonBrokenHTTPTransport(org.apache.axis.client.Service service) throws TransportNotFoundException {
return configureNonBrokenHTTPTransport(service, false);
}


public static org.apache.axis.client.Service configureNonBrokenHTTPTransport(org.apache.axis.client.Service service, boolean usewsdd) throws TransportNotFoundException {
EngineConfiguration config;


Class handlerclass = HANDLER_CLASS

if (usewsdd) {
System.out.println("Using wsdd to configure non-broken http transport");
String wsdd =
"<deployment xmlns=\"http://xml.apache.org/axis/wsdd/\"; " +
"xmlns:java=\"" + WSDDConstants.URI_WSDD_JAVA + "\">\n" +
" <transport name=\"http\" pivot=\"java:" +
handlerclass + "\"/>\n" +
/*" <service name=\"" + WSDDConstants.URI_WSDD + "\" provider=\"java:MSG\">\n" +
" <parameter name=\"allowedMethods\" value=\"AdminService\"/>\n" +
" <parameter name=\"className\" value=\"org.apache.axis.utils.Admin\"/>\n" +
" </service>\n" +*/
"</deployment>";
config = new XMLStringProvider(wsdd);
} else {
System.out.println("Programmatically configuring non-broken http transport");


/*org.apache.axis.client.Call.addTransportPackage("transport");
org.apache.axis.client.Call.setTransportForProtocol("http", transport.HTTPTransport.class);*/


EngineConfiguration defaultConfig = (EngineConfigurationFactoryFinder.newFactory()).getClientEngineConfig();
SimpleProvider provider = new SimpleProvider(defaultConfig);
Handler handler = null;
try {
handler = (Handler) handlerclass.newInstance();
} catch (IllegalAccessException iae) {
throw new TransportNotFoundException("Error instantiating handler class " + handlerclass + ": " + iae);
} catch (InstantiationException ie) {
throw new TransportNotFoundException("Error instantiating handler class " + handlerclass + ": " + ie);
} catch (ClassCastException cce) {
throw new TransportNotFoundException("handler class " + handlerclass + " is not an org.apache.axis.Handler: " + cce);
}


      SimpleTargetedChain c = new SimpleTargetedChain(handler);
      provider.deployTransport("http", c);
      config = provider;
    }

    //service.setDefaultConfiguration(config);
    //service.setEngineConfiguration(config);

    AxisClient client = new AxisClient(config);
    service.setEngine(client);

    return service;
  }

  public static class TransportNotFoundException extends Exception {
    /*public TransportNotFoundException(String message, Throwable t) {
      super(message, t);
    }*/
    public TransportNotFoundException(String message) {
      super(message);
    }
  }
}

Benjamin Flohr wrote:


Hi Aaron,

I have implemented a modified HttpSender and I think my problem is to
register this one dynamically. If you could send me the example code,

that would be


great-
thanks, benjamin



By the way, I forgot to mention, if you are sending some "official" HTTP headers, Axis will forcibly strip them. The only solution for now is to either modify the distributed HTTPSender or create your own modified HTTPSender and register it dynamically (again, I can provide code illustrating this dynamic registration).

See this bug:

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=21812

Aaron


Aaron Hamid wrote:




Implement a javax.xml.rpc.handler.GenericHandler and register it on

your


client (if sending headers) or server (if receiving headers). On the client side you need to dynamically register your handler through the handlerregistry of your service. On the server side it is a matter of editing the deployment descriptor to include your handler.

In your client handler you can do:

public boolean handleRequest(MessageContext context) {
// get the headers object
Hashtable headers = (Hashtable) context.getProperty(HTTPConstants.REQUEST_HEADERS);
if (headers == null) {
headers = new Hashtable();
context.setProperty(HTTPConstants.REQUEST_HEADERS, headers);
}


  // add a header
  String someheadervalue = (String) context.getProperty("PROPS_KEY");
  headers.put("MYHEADER", someheadervalue);

  return true;
}

Now, you ask how the handler will know what header to set. Well, you have to use the _setProperty() call on your stub to propagate information to the handler. e.g.

((javax.xml.rpc.Stub)yourapi)._setProperty("PROPS_KEY", "here is the value of the header I want to set, thank you");

As an additional treat, these properties are apparently not accessible
from the handler prior to Axis 1.1.

On the server side your handler needs to do something like:


public boolean handleRequest(javax.xml.rpc.handler.MessageContext context) {
// get the servletrequest object
HttpServletRequest request = (HttpServletRequest) context.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
if (request == null) return true;


  // look up your header
  String myheadervalue = (String) request.getHeader("MYHEADER");

System.out.println("my header was propagated with this value!: " + myheadervalue);

  return true;
}

Note that this requires usage of specific internal Axis classes/APIs (e.g. HTTPConstants properties set in the context), so it will probably

not be portable (although I imagine other frameworks will provide similar mechanisms).

I can provide sample code and/or libraries if you need.

Aaron Hamid
CIT/I&D
Cornell University

Benjamin Flohr wrote:



Hi*,

we need to access the http headers and set them using information taken from
the fully formed SOAP envelope before it is posted. We managed to do this by
modifying the HttpSender and assigning it to the call as its handler.
Unfortunately we lose the typemapping for the serializer/deserializer

and



can no
longer parse the incoming SOAP message. Is there a straightforward way

to



alter
Http headers? Can anyone help?

thanks

Andrew and Benjamin









Reply via email to