I have a JiBX binding file that specifies namespaces. However, I want to turn off namespace validation so that even an XML message with invalid namespace could be unmarshalled.
I have a binding file like the following:
<binding name="test_binding">
<namespace prefix="soapenv" uri="http://www.w3.org/2003/05/soap-envelope" />
<!-- Envelope -->
<mapping name="Envelope" ns="http://www.w3.org/2003/05/soap-envelope"
class="com.test.data.Envelope">
<structure get-method="getHeader" set-method="setHeader"
ns="http://www.w3.org/2003/05/soap-envelope" usage="optional" />
<structure get-method="getBody" set-method="setBody"
ns="http://www.w3.org/2003/05/soap-envelope" usage="optional" />
</mapping>
...
I pass the following message to JiBX unmarshaller (with different namespace for Envelope element):
<?xml version="1.0" encoding="UTF-8" ?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope">
<soapenv:Header>
<MyElement>
....
The following shows the error message when JiBX unmarshalls the message:
[Time:2011-10-04 17:39:29,802][Level:FATAL]org.jibx.runtime.JiBXException: No unmarshaller for element "{http://schemas.xmlsoap.org/soap/envelope}Envelope" (line 2, col 76)
...
Is there a way to disable namespace validation in JiBX? Thanks.
Related
I have a problem unmarshalling a RESTful request body using Spring and Jibx.
This is the request body I'm sending through Postman:
<?xml version="1.0" encoding="utf-8"?>
<locationRequest xmlns="urn:ietf:params:xml:ns:geopriv:held" responseTime="30000">
<locationType exact="true">
geodetic
civic
locationURI
</locationType>
<device xmlns="urn:ietf:params:xml:ns:geopriv:held:id">
<uri>tel:123456789;phone-context=+1</uri>
</device>
</locationRequest>
This is my binding.xml
...
<mapping name="locationRequest" class="com.example.integrations.models.LocationRequest" ordered="true">
<namespace uri="urn:ietf:params:xml:ns:geopriv:held" default="elements" />
<value name="responseTime" field="responseTime" style="attribute" usage="optional"/>
<structure name="locationType" field="locationType" map-as="locationType" usage="required"/>
<structure field="device" usage="required"/>
</mapping>
<mapping name="device" class="com.example.integrations.models.Device" >
<namespace uri="urn:ietf:params:xml:ns:geopriv:held:id" default="elements" />
<value name="uri" field="uri" />
</mapping>
<mapping abstract="true" type-name="locationType" class="com.example.integrations.models.LocationType">
<value name="exact" field="exact" style="attribute"/>
<value field="types" style="text"
serializer="com.example.integrations.ParseUtil.serializeStringList"
deserializer="com.example.integrations.ParseUtil.deserializeStringList" />
</mapping>
...
When I run the Jibx compiler everything is fine and all classes are detected and modified by the compiler correctly
This is the method that receive the web service call:
The request its unmarshalled correctly if I use a .xml file as the input, but if I go through the web service its missing some data:
...
<locationType exact="true">
geodetic
civic
locationURI
</locationType>
...
The "exact" attribute is parsed correctly, but the content, while on the xml file was parsed ok, is missing in the web service object... and for the love of me I can't figure out why.
(Note: Also the response object (LocationResponse) is not marshalled correctly when returning to Postman)
This is my Spring-servlet configuration relevant to jibx:
...
<beans:bean id="unmarshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
<beans:property name="targetClass" value="org.dellroad.jibxbindings.pidf.held.LocationRequest"/>
<beans:property name="bindingName" value="locationRequest"/>
</beans:bean>
<beans:bean id="marshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
<beans:property name="targetClass" value="org.dellroad.jibxbindings.pidf.held.LocationRequest"/>
<beans:property name="bindingName" value="locationRequest"/>
</beans:bean>
...
What am I missing here? I suspect is a missconfiguration in the Spring side
I have a C# client which produces the .NET SOAP envelope below, which works against a C# ASMX SOAP web service. However we have a Java Client calling into our service which is producing the Java envelope specified below. The main difference between the envelopes is that some values are serialised as attributes in the java client envelope rather than as XML element nodes in the C# client envelope. The java client is using AXIS WSDL2Java to generate their client. Would anyone know what I would need to tell the Java developers so they may generate the correct soap envelope for the example shown.
Kind Regards
Working SOAP Envelope Captured from C# Client
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<getDocumentPageRequest xmlns="urn:mycorp-com:MyApp.Schema.DocumentEnquiry.Messages.v01">
<header xmlns="urn:mycorp-com:MyApp.Schema.Common.Types.v01">
<extensions />
<corelationIdentifier>41edebfb-fffd-44f8-94e9-be043e1dad48</corelationIdentifier>
</header>
<securityToken xmlns="urn:mycorp-com:MyApp.Schema.Common.Types.v01">
<Value>218FD85D</Value>
</securityToken>
<documentIdentifier>15236HDFG000005</documentIdentifier>
<pageNumber>1</pageNumber>
</getDocumentPageRequest>
</soap:Body>
</soap:Envelope>
Java SOAP Envelope - Not working with web-service
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<getDocumentPageRequest
documentIdentifier="15236HDFG000005"
pageNumber="1"
xmlns="urn:mycorp-com:MyApp.Schema.DocumentEnquiry.Messages.v01">
<ns1:header corelationIdentifier="" xmlns:ns1="urn:mycorp-com:MyApp.Schema.Common.Types.v01">
<ns1:extensions/>
</ns1:header>
<ns2:securityToken xmlns:ns2="urn:mycorp-com:MyApp.Schema.Common.Types.v01">218FD85D</ns2:securityToken>
</getDocumentPageRequest>
</soapenv:Body>
</soapenv:Envelope>
Edited:: Added in WSDL as requested.
Sample WSDL and XSD Extract
Below is a sample of the WSDL generated and an extract of the XSD that it imports for the message type. I can see in this that the XML has attributes, which is what the AXIS WSDL2Java is generating, but the C# proxy and web-service is expecting XML nodes. I think this means the way the C# services is implemented is different somehow or other than the schema it is defined against. This is confusing...
<!-- WSDL Extract -->
<message name="getDocumentPageIn">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" />
<part name="messagePart" element="import0:getDocumentPageRequest" />
</message>
<message name="getDocumentPageOut">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" />
<part name="messagePart" element="import0:getDocumentPageResponse" />
</message>
<!-- import0 XSD extract -->
<xs:element name="getDocumentPageRequest">
<xs:complexType>
<xs:complexContent>
<xs:extension base="MyApp:request">
<xs:attribute name="documentIdentifier" type="xs:string" use="required"/>
<xs:attribute name="pageNumber" type="xs:short" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
Thanks for taking the time to review this, but I found the actual problem.
It turns out the C# code that was being generated for the types for the web-service and proxy was missing an [XmlAttribute] attribute in the code for each attribute defined in the XML. This caused the XmlSerializer to flatten the properties on the class to elements rather than keeping them as attributes.
My java code is taking XML messages from my local ActiveMQ queue. Now it can successfully consume messages from the queue, but it seems fails to parse it? My xml data looks like this:
#---------- #1 : ----------#
<MSG_INFO>
<message type="TextMessage" messageSelector="" originationTimestamp="" receiveTime="" jmsServerTimestamp="" jmsMsgExpiration="">
<header JMSDestination="Asurion.SYD02.Q.Business.NonPersistent.Policy.PublishTelstraAMAEnrollments" JMSDestinationType="Queue" JMSDeliveryMode="1" />
<properties>
<property name="Client" type="String">Telstra</property>
</properties>
</message>
</MSG_INFO>
BodyLength=850
<?xml version="1.0" encoding="UTF-8"?>
<ns0:PublishEnrollmentRequest xmlns:ns0="http://services.asurion.com/schemas/PolicyAdministration/PublishEnrollmentRequest/1.0">
<ns0:Parameters>
<ns0:Enrollments>
<ns0:MDN>9890667692</ns0:MDN>
<ns0:FeatureCode>MBBPHPMPS</ns0:FeatureCode>
<ns0:ProductName>MTS-SA</ns0:ProductName>
<ns0:Status>Active</ns0:Status>
<ns0:Active>Y</ns0:Active>
<ns0:EffectiveDate>2013-07-02T19:36:51-04:00</ns0:EffectiveDate>
<ns0:EnrollmentType>Customer</ns0:EnrollmentType>
<ns0:Make>UnKnown</ns0:Make>
<ns0:Model>UnKnown</ns0:Model>
<ns0:ActivationDate>2013-07-02T19:36:51-04:00</ns0:ActivationDate>
<ns0:ESN />
<ns0:IMEI />
<ns0:SubID>281474977839805</ns0:SubID>
<ns0:Operation>Enrollment Added</ns0:Operation>
</ns0:Enrollments>
</ns0:Parameters>
The exception I am getting now is:
Caused by: org.xml.sax.SAXParseException: Unexpected element: CDATA
I understand it might be the BodyLength tne that may cause this problem, but if I got rid of them, my code will not be able to extrat client information from it.
Is this something configurable in the code? Thanks.
Your data is not well-formed XML and cannot be parsed with an XML parser as-is. You'll have to find a way to separate the XML data before and after the BodyLength=850 line and parse them separately.
try to change your xml to the following if you can:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:PublishEnrollmentRequest xmlns:ns0="http://services.asurion.com/schemas/PolicyAdministration/PublishEnrollmentRequest/1.0">
<ns0:Parameters>
<ns0:Enrollments>
<ns0:MDN>9890667692</ns0:MDN>
<ns0:FeatureCode>MBBPHPMPS</ns0:FeatureCode>
<ns0:ProductName>MTS-SA</ns0:ProductName>
<ns0:Status>Active</ns0:Status>
<ns0:Active>Y</ns0:Active>
<ns0:EffectiveDate>2013-07-02T19:36:51-04:00</ns0:EffectiveDate>
<ns0:EnrollmentType>Customer</ns0:EnrollmentType>
<ns0:Make>UnKnown</ns0:Make>
<ns0:Model>UnKnown</ns0:Model>
<ns0:ActivationDate>2013-07-02T19:36:51-04:00</ns0:ActivationDate>
<ns0:ESN />
<ns0:IMEI />
<ns0:SubID>281474977839805</ns0:SubID>
<ns0:Operation>Enrollment Added</ns0:Operation>
</ns0:Enrollments>
</ns0:Parameters>
<MSG_INFO>
<message type="TextMessage" messageSelector="" originationTimestamp="" receiveTime="" jmsServerTimestamp="" jmsMsgExpiration="">
<header JMSDestination="Asurion.SYD02.Q.Business.NonPersistent.Policy.PublishTelstraAMAEnrollments" JMSDestinationType="Queue" JMSDeliveryMode="1" />
<properties>
<property name="Client" type="String">Telstra</property>
</properties>
</message>
</MSG_INFO>
<body BodyLength="850" />
</ns0:PublishEnrollmentRequest>
If you don't want to change your xml try separating you xml above and beneath BodyLength=850. and use <?xml version="1.0" encoding=utf-8"?> in the beginning of the file
I want to extract inline schema from a WSDL file. But, I don't know how to perform XSL transformation for that. Any help on creating such a stylesheet would be great.
thanks a lot,
This one is working for me:
<?xml-stylesheet type="text/xsl"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:s="http://www.w3.org/2001/XMLSchema" >
<xsl:output method="xml" />
<xsl:template match='text()' />
<xsl:template match="//s:schema">
<xsl:copy-of select='.'/>
</xsl:template>
</xsl:stylesheet>
It assumes your inline schema uses the http://www.w3.org/2001/XMLSchema namespace.
This is what you can do when the wsdl contains more than one schema-elements:
Use xsd-split.xslt from
https://gist.github.com/ebratb/3819949
to to split the *.wsdl file into several *.xsd files.
You can use the maven plugin to run the 2.0 xslt with Saxon ( see http://www.mojohaus.org/xml-maven-plugin/examples/transform-saxon.html )
Then write a small schema file that just imports those generated *.xsd files plus the official definition of the soap envelope.
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://your.company.com/dummy" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="http://<target namespace of the first xsd file>" schemaLocation="file:///path/to/first.xsd" />
<xsd:import namespace="http://<target namespace of the second xsd file>" schemaLocation="file:///path/to/second.xsd" />
...
<xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/" />
</xsd:schema>
When using a custom Resource Resolver, the schemaLocation attributes are not needed.
My Java application tries to get information from a webservice. The XML request needs to have the namespace specified in the XML root element (class name), but the namespace of the tags (class fields) need to be empty (null), otherwise the webservice rejects the request.
I have to use Spring 3.0 and Spring WS 2.0 with CastorMarshaller (currently using Castor version 1.3.1) to marshall/unmarshall my Java objects into/from XML.
Please note the __PREFIX__ and __NAMESPACE__ locations in following code snippets.
Desired marshalled output
(i.e. the desired generated SOAP request)
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" />
<soap-env:Body xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<__PREFIX__:className xmlns:__PREFIX__="__NAMESPACE__">
<fieldName>fieldValue</fieldName>
</__PREFIX__:className>
</soap-env:Body>
</soap-env:Envelope>
Currently marshalled output (i.e. the generated SOAP request)
Not adding the namespace
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" />
<soap-env:Body xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<className>
<fieldName>fieldValue</fieldName>
</className>
</soap-env:Body>
</soap-env:Envelope>
or adding the namespace to all elements
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" />
<soap-env:Body xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<__PREFIX__:className xmlns:__PREFIX__="__NAMESPACE__">
<__PREFIX__:fieldName xmlns:__PREFIX__="__NAMESPACE__">fieldValue</__PREFIX__:fieldName>
</__PREFIX__:className>
</soap-env:Body>
</soap-env:Envelope>
which are both rejected by the webservice.
My configuration
CastorMarshaller bean in applicationContext.xml
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller">
<property name="mappingLocation" value="classpath:castor-mapping.xml" />
<property name="ignoreExtraAttributes" value="true" />
<property name="ignoreExtraElements" value="true" />
<property name="namespaceMappings">
<map>
<entry key="__PREFIX__" value="__NAMESPACE__" />
</map>
</property>
</bean>
Castor Mapping file castor-mapping.xml
Not adding the namespace (namespace specified in the castorMarshaller bean through namespaceMappings should be added to the root)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
"http://castor.org/mapping.dtd">
<mapping>
<class name="some.package.ClassName">
<map-to xml="className">
<field name="fieldName" type="string">
<bind-xml name="fieldName" node="element" />
</field>
</class>
</mapping>
or adding the namespace to all elements
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
"http://castor.org/mapping.dtd">
<mapping>
<class name="some.package.ClassName">
<map-to xml="className" ns-uri="__NAMESPACE__" ns-prefix="__PREFIX__">
<field name="fieldName" type="string">
<bind-xml name="fieldName" node="element" />
</field>
</class>
</mapping>
Since I am facing the same problem, a solution that I am considering is the following:
Create a interceptor extending EndpointInterceptorAdapter
Override handleResponse method
Modify to soap message by directly access or using a transformer
public class MyEndpointInterceptorAdapter extends
EndpointInterceptorAdapter{
#Override
public boolean handleResponse(MessageContext msgContext, Object endpoint) throws IOException {
WebServiceMessage responseMsg = msgContext.getResponse();
SoapMessage soapMsg = (SoapMessage) responseMsg;
if(soapMsg!=null){
SoapEnvelope soapEnvelope=soapMsg.getEnvelope();
if(soapEnvelope!=null){
SoapBody soapbody=soapEnvelope.getBody();
if(soapbody!=null){
Source bodySource=soapbody.getSource();
if(bodySource instanceof DOMSource){
DOMSource bodyDomSource=(DOMSource)bodySource;
Node bodyNode=bodyDomSource.getNode();
if(bodyNode!=null){
NodeList bodyNodeList=bodyNode.getChildNodes();
if(bodyNodeList.getLength()!=0){
Element root=(Element)bodyNodeList.item(0);
root.setAttribute("xmlns:ns", "YourURI");
root.setPrefix("ns");
}
}
}
}
}
}
return true;
}
}