Hello Paul, unfortunately, Spring WS does not provide sophisticated configuration and customization methods of the integrated Castor marshaller/unmarshaller, to be more specific: a setter for the XMLContext. We have experienced this issue in a professional environment several times and I recommend proceeding as follows
1. extend Spring's CastorMarshaller 2. hook your Castor configuration into the lifecycle You can find a small example attached. To deal with your second problem, I'd recommend generating all types using Castor (e.g. the Castor Maven plugin[1]) from a separated XML schema (have a look at the Spring WS documentation for automatically creating a WSDL in case you aren't familiar). Don't forget to map XML namespaces to packages properly as specified in [2] before code generation. Class descriptors should then be aware of the proper namespaces. Hope that helps. Regards, Lukas PS: It would be awesome if you would provide us or the Spring team with a patch! [1] http://mojo.codehaus.org/castor-maven-plugin/ [2] http://www.castor.org/srcgen-properties.html#Mapping-XML-namespaces-to-Java-packages -------------- public class WsCastorMarshaller extends CastorMarshaller { private String[] packages = {}; private Log log = LogFactory.getLog(WsCastorMarshaller.class); @Override protected void customizeMarshaller(Marshaller marshaller) { XMLClassDescriptorResolver resolver = configureResolver(); marshaller.setResolver(resolver); } @Override protected void customizeUnmarshaller(Unmarshaller unmarshaller) { XMLClassDescriptorResolver resolver = configureResolver(); unmarshaller.setResolver(resolver); } private XMLClassDescriptorResolver configureResolver() { XMLClassDescriptorResolver resolver = (XMLClassDescriptorResolver) ClassDescriptorResolverFactory .createClassDescriptorResolver(BindingType.XML); Introspector introspector = new Introspector(); introspector.setInternalContext(marshaller.getInternalContext()); resolver.setIntrospector(introspector); try { resolver.addPackages(this.packages); } catch (ResolverException e) { log.error("Error while customizing Castor marshaller/unmarshaller.", e); } return resolver; } public void setPackages(String[] packages) { this.packages = packages; } } -------------- Am 28.01.2010 um 20:11 schrieb Paul French: > 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, finalClassLoader 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 > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email

