Hello,

 

Okay made some progress for the below.

 

I've written a simple main method to test Castor in isolation and even
though it works there looks like a bug to me which obviously causes a
problem when passing a fragment of XML to Castor to unmarshall.

 

The test program is shown below.

 

What happens is when the <usernameWRONG> element is processed castor cannot
find a descriptor for it. However before the tag <usernameWRONG> castor has
found the descriptor for <LoginRequest> as you would expect. What I don't
expect is that when Castor fails to find a descriptor for usernameWRONG it
adds all the descriptors it found for the package where the LoginRequest
lives all over again. So you end up with the same descriptor twice for some
classes in the descriptor cache.

 

Hence on subsequent calls with a valid XML doc when
XMLClassDescriptorResolverImpl.resolveByXMLName(final String xmlName, final
String namespaceURI, final ClassLoader loader) is called it finds 2 possible
matches for a descriptor. In the standalone program it manages to resolve to
one of these since the namespace is set explicitly. When used from within
Spring Web Services it cannot resolve a descriptor from the 2 possible
matches since I assume the namespace is not set explicitly in the XML doc
since the namespace declaration is defined in SOAP header.

 

Any ideas how to progress this? Someone can bring the whole web service down
by simply sending a slightly incorrect SOAP request.

 

Thanks

Paul

 

 

 

  public static void main(String[] args) throws Exception

  {

    XMLContext context = new XMLContext();

    context.addPackages(new
String[]{"com.kirona.mitie.model.web.server.concept","com.kirona.mitie.model
.web.server.concept.types"});

    

    Unmarshaller unMarshaller = context.createUnmarshaller();

    try

    {

      System.out.println("TEST 1 - this will fail due to incorrect XML tag
usernameWRONG");

      LoginRequest loginRequest = (LoginRequest) unMarshaller.unmarshal(new
StringReader("<sch:LoginRequest
xmlns:sch=\"http://kirona.com/2009/12/Concept/schema/\";>\n"+

      "<sch:usernameWRONG>paul</sch:usernameWRONG>\n"+

      "<sch:password>password</sch:password>\n"+

      "</sch:LoginRequest>"));

      System.out.println("TEST 1 OK");

    }

    catch (Exception e)

    {

      e.printStackTrace();

    }

 
System.out.println("\n\n****************************************************
*************\n\n");

    try

    {

      System.out.println("TEST 2");

      LoginRequest loginRequest = (LoginRequest) unMarshaller.unmarshal(new
StringReader("<sch:LoginRequest
xmlns:sch=\"http://kirona.com/2009/12/Concept/schema/\";>\n"+

          "<sch:username>paul</sch:username>\n"+

          "<sch:password>arsenal</sch:password>\n"+

          "</sch:LoginRequest>"));

      System.out.println("TEST 2 OK");

    }

    catch (Exception e)

    {

      e.printStackTrace();

    }

 
System.out.println("\n\n****************************************************
*************\n\n");

  }

 

 

 

 

From: Paul French [mailto:[email protected]] 
Sent: 28 January 2010 13:11
To: '[email protected]'
Subject: Very Strange Problem

 

Hello, we use Spring-WS and castor 1.3.1 for unmarshalling and marshalling.
Spring-WS provides a class CastorMarshaller to handle the unmarshalling and
marshalling for you. We have had to override one method in this class since
it does not support adding descriptors to the XMLContext.

 

So we have a bunch of model objects (as well as the .castor.cdr files) and a
bunch of descriptors which are registered with the XMLContext using the
addPackage(packageDescriptor) method

 

When we make a call like:

 

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/";
xmlns:sch="http://kirona.com/2009/12/Concept/schema/";>

   <soapenv:Header/>

   <soapenv:Body>

      <sch:LoginRequest>

         <sch:username>username</sch:username>

         <sch:password>password</sch:password>

      </sch:LoginRequest>

   </soapenv:Body>

</soapenv:Envelope>

 

.the request is marshalled fine.

 

If we then make a mistake in the SOAP request e.g.

 

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/";
xmlns:sch="http://kirona.com/2009/12/Concept/schema/";>

   <soapenv:Header/>

   <soapenv:Body>

      <sch:LoginRequest>

         <sch:usernameWRONG>xxxx</sch:usernameWRONG>

         <sch:password>xxxxxx</sch:password>

      </sch:LoginRequest>

   </soapenv:Body>

</soapenv:Envelope>

 

.we get the error  (in the SOAP fault respone)

 

"Castor unmarshalling exception: unable to find FieldDescriptor for
'usernameWRONG' in ClassDescriptor of LoginRequest; nested exception is
org.exolab.castor.xml.MarshalException: unable to find FieldDescriptor for
'usernameWRONG' in ClassDescriptor of LoginRequest"

 

.which makes sense. However if I repeat the incorrect SOAP request I
get......

 

"Castor unmarshalling exception: The class for the root element
'LoginRequest' could not be found.; nested exception is
org.exolab.castor.xml.MarshalException: The class for the root element
'LoginRequest' could not be found."

 

..it seems to no longer know what the element LoginRequest is anymore??

 

If I correct the SOAP request it still does not work, I still get the
previous error. 

 

I can get things to work again by re-structuring the SOAP request as follows
(by moving the namespace declaration):

 

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/";>

   <soapenv:Header/>

   <soapenv:Body>

      <sch:LoginRequest
xmlns:sch="http://kirona.com/2009/12/Concept/schema/";>

         <sch:username>username</sch:username>

         <sch:password>password</sch:password>

      </sch:LoginRequest>

   </soapenv:Body>

</soapenv:Envelope>

 

.and from this point onwards this is the only way it will work.

 

I know this is a bit SOAP related but it is the marshalling layer that is
failing. Any ideas?

 

P

 

Reply via email to