|
Hi Everyone:
I actually discovered the cause of my problem, and searching
through this list's archives, I believe the same solution would apply to many
others who have experienced similar issues. In the end, the solution was so
simple that I'm almost embarrassed to post it here.
The problem had nothing to do with Castor (de)serialization
or the AxisClient class. The problem lie in the fact that I was using a
ClientHandler to support WSSE [http://axis-wsse.sourceforge.net/]. Nevertheless,
the ClientHandler itself was not the problem (in fact, I highly recommend it for
simple Username/Password WSSE support). It was the fact that
the "setClientHandlers" method was called that was the problem. This member
of the org.apache.axis.client.Call class ends up calling its sibling
member "setSOAPService" with a new SOAPService object. The
SOAPService object is set as a private member of the Call object [with a
variable name of "myService"].
This is all fine until the Call.invoke() method is executed
by the SoapStub. It is within the logic of this method that "myService" is set
to the MessageContext object. NOW THE PROBLEM BEGINS, for it is within the
"setService" member of the MessageContext object that the MessageContext's
encoding type is set to SOAP encoding. Since the service was using SOAP
v1.1, the actual value of the encoding became: "http://schemas.xmlsoap.org/soap/encoding/". However, if we refer back to the SoapStub object that
was generated by WSDL2Java, we see that the encoding under which the
TypeMappingRegistry was created was "null". The TypeMappingRegistry that
had been created is no longer visible to objects that are
now attempting to retrieve TypeMappings for the SOAP1_1
encoding.
Perhaps it should have been obvious to me that I would have
to edit the encoding within the SoapStub object simply because I added a
ClientHandler, but it was not. Regardless, the solution was to change the
following line in the "createCall" member of the
SoapStub from:
_call.setEncodingStyle(null);
to:
_call.setEncodingStyle(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS.getEncodingURI());
AXIS
v1.2beta code snippets shown to
illustrate
==================
<WSDL2Java-Generated>SoapStub.createCall():
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)); } // ***Added for WSSE
support***
_call.setProperty(WsseClientHandler.PASSWORD_OPTION, WsseClientHandler.PASSWORD_CLEARTEXT); _call.setClientHandlers(new WsseClientHandler(), null);
// 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.setEncodingStyle(null); <=== Encoding under which TypeMappingRegistry gets indexed 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); } } ==================
Call.setClientHandlers(Handler, Handler:
{ // Create a SOAPService which will be used as the client-side service // handler. setSOAPService(new SOAPService(reqHandler, null, respHandler)); <=== new SOAPService } ==================
Call.setSOAPService(SOAPService):
public void setSOAPService(SOAPService
service)
{ myService = service; <=== myService gets set in the Call object if (service != null) { // Set the service so that it defers missing property gets to the // Call. So when client-side Handlers get at the MessageContext, // the property scoping will be MC -> SOAPService -> Call -> Engine // THE ORDER OF THESE TWO CALLS IS IMPORTANT, since setting the // engine on a service will set the property parent for the service service.setEngine(this.service.getAxisClient()); service.setPropertyParent(myProperties); } } ==================
Call.invoke():
<snip>
// Determine client target service if (myService != null) { <=== myService is not null; it was automatically set when setClientHandlers was called // If we have a SOAPService kicking around, use that directly msgContext.setService(myService); <===SOAPService set in MessageContext } else { if (portName != null) { // No explicit service. If we have a target service name, <snip> ==================
MessageContext.setService(SOAPService):
public void setService(SOAPService sh) throws
AxisFault
{ log.debug("MessageContext: setServiceHandler("+sh+")"); serviceHandler = sh; if (sh != null) { targetService = sh.getName(); SOAPService service = sh; TypeMappingRegistry tmr = service.getTypeMappingRegistry(); setTypeMappingRegistry(tmr); //
styles are not "soap version aware" so
compensate...
setEncodingStyle(service.getUse().getEncoding()); <=== Encoding style updated //
This MessageContext should now defer properties it can't
find
// to the Service's options. bag.setParent(sh.getOptions()); //
Note that we need (or don't need) high-fidelity SAX
recording
// of deserialized messages according to the setting on the // new service. highFidelity = service.needsHighFidelityRecording();
service.getInitializedServiceDesc(this);
} } ==================
-----Original Message-----
From: Jana Poornavel [mailto:[EMAIL PROTECTED] Sent: Thursday, June 10, 2004 12:59 AM To: [EMAIL PROTECTED] Subject: RE: TypeMappingRegistry getting "lost" during call Hi
cameron,
How do you load your Deserializing classes? Or let me put it this way,does your
serializer Exist in your classpath
? Regards, jana Janarthanan
Poornavel www.OrangeScape.com From: Cameron
F. Logan [mailto:[EMAIL PROTECTED] I am developing an Axis-Castor based
client application for a series of .NET web services using Axis v1.1 and Castor
v0.9.5.3. I have built Axis using the Castor libraries, so the
CastorDeserializer is available to me. I have used WSDL2Java to generate client
proxies for the services. As per usual with the WSDL2Java generated proxy
code, the type mapping information is loaded programmatically and I manually
changed the BeanSerializer... entries to CastorSerializer
entries. Still, I have been
receiving a "Deserializer not found" error upon execution of my client code
and have painstakingly traced this down to a problem with either the
MessageContext or the TypeMappingRegistry being effectively reset after the
pivot. I can resolve the proper TypeMapping object for the each given response
message successfully until the code hits the AxisClient class. Then the
TypeMapping starts to resolve to null. I have tried included the
client-config.wsdd file as an alternate means of providing type mapping
information, but that yields the same error. I know that this isn't a problem
with the Axis/Castor integration because I am able to avoid the error and make
successful calls to the web services by hard-coding the deserializer in the Call
object to be the CastorDeserialzer. Obviously, I do not want to hard
code the deserializer this way, but so far it is the only thing that has seemed
to work. Can anyone shed light on why or how
the TypeMapping information is cleared out half-way through the interaction with
the web service? What could possibly be wrong? I can provide oodles of code if
necessary, but thought I would start with the brief description of the problem.
This is driving me crazy! Thanks, Cameron ______________________________ |
- TypeMappingRegistry getting "lost" during call Cameron F. Logan
- RE: TypeMappingRegistry getting "lost" dur... Jana Poornavel
- Re: TypeMappingRegistry getting "lost"... Cameron F. Logan
- Re: TypeMappingRegistry getting "lost&q... Davanum Srinivas
