Announcement Announcement Module
Collapse
No announcement yet.
Missing namespace with Castor and WebServiceTemplate Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Missing namespace with Castor and WebServiceTemplate

    I'm having problems writing a client that uses the WebServiceTemplate and Castor. It looks like the namespace is being dropped during the marshalling process and leads to malformed xml.

    I've verified this by taking the mapping file and running a stand-alone test using Castor. Here's what I get:

    <?xml version="1.0" encoding="UTF-8"?>
    <user:SaveUserRequest xmlns:user="http://www.nova.org/spring-ws/user">
    <user:name>Name</user:name>
    <user:age>22</user:age>
    <user:job>Programmer</user:job>
    </user:SaveUserRequest>

    When I use that same mapping file in my client, the soap message looks like this (according to tcpmon):
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header />
    <SOAP-ENV:Body>
    <user:SaveUserRequest>
    <user:name>Name</user:name>
    <user:age>22</user:age>
    <user:job>Programmer</user:job>
    </user:SaveUserRequest>
    </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>

    Any ideas on what's going on?

  • #2
    Looks like a XML parser problem, i.e. Xerces. What JDK are you using, are you adding Xerces to the classpath?

    Comment


    • #3
      I'm using 1.4.2 and Xerces 2.8.0.

      Comment


      • #4
        Ah, that's what I though. As explained here:

        Finally, a bit of a warning about XML parsing on JDK 1.4: it's a mess. Some namespace-specific functionality simply doesn't work. Unfortunately there is nothing I can do about it, because you cannot use the classpath to override the default (Crimson) XML parser, nor the old version of Xalan that is bundled with JDK 1.4. See this FAQ entry on the Xalan site, and also this entry on the Xerces site. The only thing that works is to add newer versions of Xerces and Xalan in the lib/endorsed directory of your JDK, as explained in those FAQs.

        Comment


        • #5
          Sure enough - I switched to 1.5 and everything works fine.

          Thanks for helping with this.

          Comment


          • #6
            Hi, I've got a client side Castor issue. Everything is working nice and simply, except for the unmarshalling.

            I'm using the WebServiceTemplate to send and receive, and also attempting marshalling/unmarshalling.

            Basic source/result stuff works. I get this fine looking response:

            Code:
            <?xml version="1.0" encoding="UTF-8"?>
            <response>
            	<result-code>SUCCESS</result-code>
            	<result-status>SUCCESS</result-status>
            	<engine>VACM</engine>
            	<engine-status>VOTING</engine-status>
            	<command>OTHER</command>
            	<CVI xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            		xsi:nil="true" />
            	<score>0.0</score>
            	<message />
            	<time-to-execute>16</time-to-execute>
            	<transaction-id>
            		b95c7d5e-0114-fea5-dd5c-ac118424aa77
            	</transaction-id>
            	<attributes>
            		<attribute>
            			<name>engine.version</name>
            			<value>2.00.00</value>
            		</attribute>
            	</attributes>
            	<child-results xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            		xsi:nil="true" />
            </response>

            When I use Castor to unmarshall (with a Response class), i get namespace problems:

            I'm using JDK1.6.


            Code:
            org.springframework.oxm.castor.CastorUnmarshallingFailureException: Castor unmarshalling exception: The namespace associated with the prefix 'xsi' could not be resolved.; nested exception is org.exolab.castor.xml.MarshalException: The namespace associated with the prefix 'xsi' could not be resolved.
            Caused by: org.exolab.castor.xml.MarshalException: The namespace associated with the prefix 'xsi' could not be resolved.
            	at org.exolab.castor.xml.Unmarshaller.convertSAXExceptionToMarshalException(Unmarshaller.java:755)
            	at org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:634)
            	at org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:741)
            	at org.springframework.oxm.castor.CastorMarshaller.unmarshalDomNode(CastorMarshaller.java:239)
            	at org.springframework.oxm.AbstractMarshaller.unmarshalDomSource(AbstractMarshaller.java:286)
            	at org.springframework.oxm.AbstractMarshaller.unmarshal(AbstractMarshaller.java:120)
            	at org.springframework.ws.support.MarshallingUtils.unmarshal(MarshallingUtils.java:57)
            	at org.springframework.ws.client.core.WebServiceTemplate$2.extractData(WebServiceTemplate.java:267)
            	at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:408)
            	at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:256)
            	at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:244)
            	at com.vecommerce.kaz.WebServiceClient.simpleMarshalledRequest(WebServiceClient.java:58)
            	at com.vecommerce.kaz.WebServiceClient.customSendAndReceive(WebServiceClient.java:85)
            	at com.vecommerce.kaz.WebServiceClient.main(WebServiceClient.java:90)
            Caused by: org.xml.sax.SAXException: The namespace associated with the prefix 'xsi' could not be resolved.
            	at org.exolab.castor.xml.UnmarshalHandler.processAttributeList(UnmarshalHandler.java:3229)
            	at org.exolab.castor.xml.UnmarshalHandler.startElement(UnmarshalHandler.java:1406)
            	at org.exolab.castor.xml.util.DOMEventProducer.process(DOMEventProducer.java:246)
            	at org.exolab.castor.xml.util.DOMEventProducer.process(DOMEventProducer.java:183)
            	at org.exolab.castor.xml.util.DOMEventProducer.processChildren(DOMEventProducer.java:334)
            	at org.exolab.castor.xml.util.DOMEventProducer.process(DOMEventProducer.java:248)
            	at org.exolab.castor.xml.util.DOMEventProducer.process(DOMEventProducer.java:183)
            	at org.exolab.castor.xml.util.DOMEventProducer.start(DOMEventProducer.java:111)
            	at org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:631)
            	... 12 more
            Caused by: org.xml.sax.SAXException: The namespace associated with the prefix 'xsi' could not be resolved.
            	at org.exolab.castor.xml.UnmarshalHandler.processAttributeList(UnmarshalHandler.java:3229)
            	at org.exolab.castor.xml.UnmarshalHandler.startElement(UnmarshalHandler.java:1406)
            	at org.exolab.castor.xml.util.DOMEventProducer.process(DOMEventProducer.java:246)
            	at org.exolab.castor.xml.util.DOMEventProducer.process(DOMEventProducer.java:183)
            	at org.exolab.castor.xml.util.DOMEventProducer.processChildren(DOMEventProducer.java:334)
            	at org.exolab.castor.xml.util.DOMEventProducer.process(DOMEventProducer.java:248)
            	at org.exolab.castor.xml.util.DOMEventProducer.process(DOMEventProducer.java:183)
            	at org.exolab.castor.xml.util.DOMEventProducer.start(DOMEventProducer.java:111)
            	at org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:631)
            	at org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:741)
            	at org.springframework.oxm.castor.CastorMarshaller.unmarshalDomNode(CastorMarshaller.java:239)
            	at org.springframework.oxm.AbstractMarshaller.unmarshalDomSource(AbstractMarshaller.java:286)
            	at org.springframework.oxm.AbstractMarshaller.unmarshal(AbstractMarshaller.java:120)
            	at org.springframework.ws.support.MarshallingUtils.unmarshal(MarshallingUtils.java:57)
            	at org.springframework.ws.client.core.WebServiceTemplate$2.extractData(WebServiceTemplate.java:267)
            	at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:408)
            	at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:256)
            	at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:244)
            	at com.vecommerce.kaz.WebServiceClient.simpleMarshalledRequest(WebServiceClient.java:58)
            	at com.vecommerce.kaz.WebServiceClient.customSendAndReceive(WebServiceClient.java:85)
            	at com.vecommerce.kaz.WebServiceClient.main(WebServiceClient.java:90)
            I've looked at creating my own unmarshaller, but it looks like something is broken at a more fundamental level with Castor.

            Is there something else I can do to get unmarshalling working?

            Comment


            • #7
              Well, you could try to get rid of the xsi prefix on the server-side . Or perhaps use another marshaller. Finally, you could consider mailing the Castor lists, because it really is a Castor issue.

              Comment


              • #8
                I wrote my own CastorUnmarshaller based your code. Unfortunately, all the relevent methods in the CastorMarshaller class are final (!), so extending it is not an option. What about include the source code in the download?

                In essence, I just strip all the attributes from the reply node. This wouldn't work for everybody though. Probably better to selectively remove the namespaced atttributes only.

                Code:
                import java.io.IOException;
                import java.io.InputStream;
                import java.io.OutputStream;
                import java.io.OutputStreamWriter;
                import java.io.Reader;
                import java.io.Writer;
                
                import javax.xml.stream.XMLEventReader;
                import javax.xml.stream.XMLEventWriter;
                import javax.xml.stream.XMLStreamReader;
                import javax.xml.stream.XMLStreamWriter;
                import javax.xml.transform.dom.DOMResult;
                
                import org.exolab.castor.mapping.Mapping;
                import org.exolab.castor.mapping.MappingException;
                import org.exolab.castor.xml.MarshalException;
                import org.exolab.castor.xml.Marshaller;
                import org.exolab.castor.xml.UnmarshalHandler;
                import org.exolab.castor.xml.Unmarshaller;
                import org.exolab.castor.xml.ValidationException;
                import org.exolab.castor.xml.XMLContext;
                import org.exolab.castor.xml.XMLException;
                import org.springframework.beans.factory.InitializingBean;
                import org.springframework.core.io.ClassPathResource;
                import org.springframework.core.io.Resource;
                import org.springframework.oxm.AbstractMarshaller;
                import org.springframework.oxm.XmlMappingException;
                import org.springframework.oxm.castor.CastorSystemException;
                import org.springframework.oxm.castor.CastorUnmarshallingFailureException;
                import org.springframework.oxm.castor.CastorUtils;
                import org.w3c.dom.Element;
                import org.w3c.dom.NamedNodeMap;
                import org.w3c.dom.Node;
                import org.w3c.dom.NodeList;
                import org.xml.sax.ContentHandler;
                import org.xml.sax.InputSource;
                import org.xml.sax.SAXException;
                import org.xml.sax.XMLReader;
                import org.xml.sax.ext.LexicalHandler;
                
                
                public class CastorUnmarshaller extends AbstractMarshaller implements InitializingBean {
                
                	public CastorUnmarshaller() {}
                	
                	public CastorUnmarshaller(Resource mappingResource) {
                		this.mappingLocation = mappingResource;
                	}
                	
                    @Override
                	protected void marshalXmlEventWriter(Object arg0, XMLEventWriter arg1) throws XmlMappingException {
                		
                	}
                
                	@Override
                	protected void marshalXmlStreamWriter(Object arg0, XMLStreamWriter arg1) throws XmlMappingException {
                		
                	}
                
                	@Override
                	protected Object unmarshalXmlEventReader(XMLEventReader arg0) throws XmlMappingException {
                		return null;
                	}
                
                	@Override
                	protected Object unmarshalXmlStreamReader(XMLStreamReader arg0) throws XmlMappingException {
                		return null;
                	}
                
                	@Override
                	public boolean supports(Class arg0) {
                		return true;
                	}
                	
                
                	
                	void stripAtts(Node node) {
                		NamedNodeMap map = node.getAttributes();
                		
                		if (map != null) {
                			Element el = (Element) node;
                			for (int i = 0; i < map.getLength(); i++) {
                				el.removeAttribute(map.item(i).getNodeName());			
                			}
                		}
                		NodeList list = node.getChildNodes();
                		for (int i = 0; i < list.getLength(); i++) {
                			stripAtts(list.item(i));
                		}
                	}
                	
                	@Override
                	protected Object unmarshalDomNode(Node node) throws XmlMappingException {
                		
                		stripAtts(node);
                		
                		Object result = null;
                		
                		try {
                			
                			Mapping mapping = XMLContext.createMapping();
                			mapping.loadMapping(this.mappingLocation.getURL());
                			
                			XMLContext context = new XMLContext();
                			context.addMapping(mapping);
                
                			Unmarshaller castorUnmarshaller =  context.createUnmarshaller();
                			castorUnmarshaller.setClass(Response.class);
                			result = castorUnmarshaller.unmarshal(node);
                		} catch (MarshalException e) {
                			// TODO Auto-generated catch block
                			e.printStackTrace();
                		} catch (ValidationException e) {
                			// TODO Auto-generated catch block
                			e.printStackTrace();
                		} catch (IOException e) {
                			// TODO Auto-generated catch block
                			e.printStackTrace();
                		} catch (MappingException e) {
                			// TODO Auto-generated catch block
                			e.printStackTrace();
                		}
                		return result;
                	}
                	
                    public static final String DEFAULT_ENCODING = "UTF-8";
                
                    private Resource mappingLocation;
                
                    private String encoding;
                
                    private Mapping mapping;
                
                    private Unmarshaller unmarshaller;
                
                	private Class clazz;
                
                    private String getEncoding() {
                        return (encoding != null) ? encoding : DEFAULT_ENCODING;
                    }
                
                
                    public void setEncoding(String encoding) {
                        this.encoding = encoding;
                    }
                
                
                    public void setMapping(Mapping mapping) {
                        this.mapping = mapping;
                    }
                
                    public void setMappingLocation(Resource mappingLocation) {
                        this.mappingLocation = mappingLocation;
                    }
                
                    public final void afterPropertiesSet() throws Exception {
                        if ((mappingLocation != null) && (mapping == null)) {
                            Mapping castorMapping = new Mapping();
                            InputStream inputStream = mappingLocation.getInputStream();
                            try {
                                castorMapping.loadMapping(new InputSource(inputStream));
                                this.mapping = castorMapping;
                            }
                            finally {
                                inputStream.close();
                            }
                        }
                        if (mapping != null) {
                            try {
                                unmarshaller = new Unmarshaller(mapping);
                            }
                            catch (MappingException ex) {
                                throw new CastorSystemException("Could not load Castor mapping: " + ex.getMessage(), ex);
                            }
                        }
                        else {
                            unmarshaller = new Unmarshaller(clazz);
                        }
                    }
                
                    /**
                     * Converts the given <code>CastorException</code> to an appropriate exception from the
                     * <code>org.springframework.oxm</code> hierarchy.
                     * <p/>
                     * The default implementation delegates to <code>CastorUtils</code>. Can be overridden in subclasses.
                     * <p/>
                     * A boolean flag is used to indicate whether this exception occurs during marshalling or unmarshalling, since
                     * Castor itself does not make this distinction in its exception hierarchy.
                     *
                     * @param ex          Castor <code>XMLException</code> that occured
                     * @param marshalling indicates whether the exception occurs during marshalling (<code>true</code>), or
                     *                    unmarshalling (<code>false</code>)
                     * @return the corresponding <code>XmlMappingException</code>
                     * @see CastorUtils#convertXmlException
                     */
                    public XmlMappingException convertCastorException(XMLException ex, boolean marshalling) {
                        return CastorUtils.convertXmlException(ex, marshalling);
                    }
                
                    private void marshal(Object graph, Marshaller marshaller) {
                        try {
                            if (mapping != null) {
                                marshaller.setMapping(mapping);
                            }
                            marshaller.marshal(graph);
                        }
                        catch (MappingException ex) {
                            throw new CastorSystemException("Could not load Castor mapping", ex);
                        }
                        catch (XMLException ex) {
                            throw convertCastorException(ex, true);
                        }
                    }
                    
                    protected void marshalDomNode(Object graph, Node node) throws XmlMappingException {
                        Marshaller marshaller = new Marshaller(node);
                        marshal(graph, marshaller);
                    }
                
                    protected void marshalOutputStream(Object graph, OutputStream outputStream)
                            throws XmlMappingException, IOException {
                        OutputStreamWriter writer = new OutputStreamWriter(outputStream, getEncoding());
                        marshalWriter(graph, writer);
                    }
                
                    protected void marshalSaxHandlers(Object graph, ContentHandler contentHandler, LexicalHandler lexicalHandler)
                            throws XmlMappingException {
                        try {
                            Marshaller marshaller = new Marshaller(contentHandler);
                            marshal(graph, marshaller);
                        }
                        catch (IOException ex) {
                            throw new CastorSystemException("Could not construct Castor ContentHandler Marshaller", ex);
                        }
                    }
                
                    protected void marshalWriter(Object graph, Writer writer) throws XmlMappingException, IOException {
                        Marshaller marshaller = new Marshaller(writer);
                        marshal(graph, marshaller);
                    }
                
                
                    @Override
                    protected void marshalDomResult(Object graph, DOMResult domResult) throws XmlMappingException {
                    	
                    	super.marshalDomResult(graph, domResult);
                    }
                    
                    protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource)
                            throws XmlMappingException, IOException {
                        UnmarshalHandler unmarshalHandler = unmarshaller.createHandler();
                        try {
                			unmarshalHandler.startPrefixMapping("xsi", "http://www.w3.org/2001/XMLSchema-instance");
                		} catch (SAXException e) {
                			// TODO Auto-generated catch block
                			e.printStackTrace();
                		}
                        try {
                            ContentHandler contentHandler = Unmarshaller.getContentHandler(unmarshalHandler);
                            xmlReader.setContentHandler(contentHandler);
                            xmlReader.parse(inputSource);
                            return unmarshalHandler.getObject();
                        }
                        catch (SAXException ex) {
                            throw new CastorUnmarshallingFailureException(ex);
                        }
                    }
                
                    protected Object unmarshalInputStream(InputStream inputStream) throws XmlMappingException, IOException {
                        try {
                            return unmarshaller.unmarshal(new InputSource(inputStream));
                        }
                        catch (XMLException ex) {
                            throw convertCastorException(ex, false);
                        }
                    }
                
                    protected Object unmarshalReader(Reader reader) throws XmlMappingException, IOException {
                        try {
                            return unmarshaller.unmarshal(new InputSource(reader));
                        }
                        catch (XMLException ex) {
                            throw convertCastorException(ex, false);
                        }
                    }
                
                	public void setTargetClass(Class clazz) {
                		this.clazz = clazz;	
                	}
                }

                Comment


                • #9
                  If you download the full distribution, the sources are included.

                  As for the final methods: if you create a JIRA issue, I will take a look at it.

                  Comment


                  • #10
                    Apologies. I found the source under modules. I was expecting projects or src. In any case, very nice work and thanks!

                    Comment


                    • #11
                      Did you raise the issue ?
                      Did you solve it ?

                      I have the same problem for the moment.

                      Thanks !

                      xml is
                      Code:
                      <?xml version="1.0" encoding="UTF-8"?>
                      <checkVatResponse>
                      	<countryCode>BE</countryCode>
                      	<vatNumber>123456789</vatNumber>
                      	<requestDate>2007-11-29</requestDate>
                      	<valid xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:boolean">false</valid>
                      	<name/>
                      	<address/>
                      </checkVatResponse>

                      Comment


                      • #12
                        unmarshalling exception with missing namespace

                        Hi,

                        It has been a year since this post but I still get th eproblem with speing ws 1.5.4, castor 1.2. I ended up following the tip here & modifying the code just to ignore the attribute in question. Even though I can set properties on the bean like namespacemappings and ignoreExtraAttributes, it did not help.

                        Can we raise a JIRA issue re this?

                        Thanks

                        -rose

                        Comment


                        • #13
                          Hi all,

                          the issue seems to be still present in spring-2.5.6

                          is there another fix / workaround for this?

                          or is it so uncommon to use xsd:nillable elements in Web Services? (is it WSI-compliant btw?)

                          thx and regards,
                          the debugger (not)

                          freeze dried maqui berry
                          apple cider vinegar for acne
                          Last edited by DebugMeNot; May 30th, 2011, 09:41 PM.

                          Comment


                          • #14
                            I don't use Castor anymore - I don't think it supports namespaces very well - so now I use jaxb - more fiddly setting up but definitely worth it when you have a large webservice with all the wsdls and schemas provided.

                            If you can't use jaxb then probably best just to write your own unmarshaller.

                            Comment

                            Working...
                            X