Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Missing namespace with Castor and WebServiceTemplate

  1. #1

    Default 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. #2
    Join Date
    Jul 2005
    Location
    Rotterdam, the Netherlands
    Posts
    1,562

    Default

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

    Spring Web Services Dev Lead
    Please read the FAQ

  3. #3

    Default

    I'm using 1.4.2 and Xerces 2.8.0.

  4. #4
    Join Date
    Jul 2005
    Location
    Rotterdam, the Netherlands
    Posts
    1,562

    Default

    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.
    Arjen Poutsma

    Spring Web Services Dev Lead
    Please read the FAQ

  5. #5

    Default

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

    Thanks for helping with this.

  6. #6
    Join Date
    Mar 2006
    Location
    Sydney
    Posts
    27

    Default

    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?

  7. #7
    Join Date
    Jul 2005
    Location
    Rotterdam, the Netherlands
    Posts
    1,562

    Default

    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.
    Arjen Poutsma

    Spring Web Services Dev Lead
    Please read the FAQ

  8. #8
    Join Date
    Mar 2006
    Location
    Sydney
    Posts
    27

    Default

    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;	
    	}
    }

  9. #9
    Join Date
    Jul 2005
    Location
    Rotterdam, the Netherlands
    Posts
    1,562

    Default

    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.
    Arjen Poutsma

    Spring Web Services Dev Lead
    Please read the FAQ

  10. #10
    Join Date
    Mar 2006
    Location
    Sydney
    Posts
    27

    Default

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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •