this is my first question, so please be gentle ;)
I'm stuck with a weird problem. Essentially i get three XSD definitions like the following:
PartA.xsd
targetNameSpace="PartA"
include="PartB.xsd"
PartB.xsd
<!-- no namespace definition!!! -->
PartC.xsd
targetNameSpace="PartC"
inlude="PartB.xsd"
import="PartA.xsd"
The error pops up, when binding PartC via JAXB to Java classes:
A class/interface with the same name "b.exampleType" is already in use. Use a class customization to resolve this conflict.
This confusing error happened most likely because the schema uses a technique called "chameleon schema", which causes a single definition to be loaded multiple times into different namespaces. See http://forums.java.net/jive/thread.jspa?threadID=18631 for more about this.
Following the link, i found out, the actual error lies in PartB, which has no namespace declaration! This method is called Chameleon Schema. The defined types in PartB will adopt the namesspace of the importing XSD.
So in my case, there are two namespaces for the same type:
"PartA"
"PartC"
And this is, where JAXB breaks down. I haven't found a way to bind PartC properly. And (to make things tricky) i have chance to change the original XSD definitions!
Has anyone come across this phenomena or something like that before and has a valid workaround for it?
I was facing the same problem using wsdl2java:
WSDLToJava Error: Thrown by JAXB : A class/interface with the same
name "Respuesta" is already in use. Use a class customization to
resolve this conflict.
But this question pointed me in the right direction.
Using wsdl2java from CFX you can customize how elements are binded to classes using a binding.xml file.
For example:
/Applications/apache-cxf-2.7.13/bin/wsdl2java -b ./src/main/resources/binding.xml -V -d src/main/java -compile -classdir target/classes http://someurl.wsdl
The key is to explain in the binding.xml to name certain xsd element with one especific className to avoid colissions:
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<jxb:bindings schemaLocation="./someXsdFile.xsd">
<!-- Rename the respuesta class to resolve a naming conflict with other Respuesta element already defined-->
<jxb:bindings node="//xs:element[#name='respuesta']/xs:complexType">
<jxb:class name="Respuesta2" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
Hope this helps to the next person with this problem using wsdl2java. I supose that other tools should allow similar aproaches to this problem.
I was having the same issue and the google search landed me here.
Your question is detailed enough and I was able to find the answer,
what I did is put the namespace in PartB.xsd and use XJC to generate the java classes.
I added the following:
xmlns:ns="http://www.myCompany.com/2009/01/CustSchema" targetNamespace="http://www.myCompany.com/2009/01/CustSchema"
The following is available, although it does not provide a lot of detail:
https://javaee.github.io/jaxb-v2/doc/user-guide/ch03.html#compiling-xml-schema-how-modularization-of-schema-interacts-with-xjc
There is one workaround for this problem. More specifically what you have to do is:
1.Define proxy schema (PartB_proxy.xsd) for PartB.xsd (with no namespace definition) and specify temporary namespace (for example PartB):
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns="PartB"
targetNamespace="PartB">
<xsd:include schemaLocation="partB.xsd"/>
2.Prepare bindings file (for large schemas this step could be automatized by generating episode file - more details in my article - I've attached link at the end of this post) - this step is required to avoid generating duplicate classes for PartB schema (by default the duplicate classes that come from PartB schema will be generated for PartA and PartC schemas/java packages):
<bindings version="2.1" xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<bindings scd="x-schema::partA" xmlns:partA="PartA">
<bindings scd="~partA:SomeType1">
<class ref="SomeType1"/>
</bindings>
<bindings scd="~partA:SomeType2">
<class ref="SomeType2"/>
</bindings>
</bindings>
<bindings scd="x-schema::partC" xmlns:partC="PartC">
<bindings scd="~partC:SomeType1">
<class ref="SomeType1"/>
</bindings>
<bindings scd="~partC:SomeType2">
<class ref="SomeType2"/>
</bindings>
</bindings>
</bindings>
3.Generate JAXB classes using XJC, example Gradle task (I am using Moxy implemetnation but You can use default XJC generator from JDK 8 or standalone JAXB library for newer JDK versions):
task generateExampleChameleonSourcesWithMoxy(type: JavaExec) {
classpath = configurations.moxy
main = 'org.eclipse.persistence.jaxb.xjc.MOXyXJC'
args '-b'
args 'src/main/resources/example/chameleon/bindings.xml'
args '-d'
args 'src/main/generated'
args 'src/main/resources/example/chameleon/PartA.xsd'
args 'src/main/resources/example/chameleon/PartB_proxy.xsd'
args 'src/main/resources/example/chameleon/PartC.xsd'
}
4.Remove proxy namespace (partB) from package-info.java generated for partB schema:
javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package partB;
5.Finally You can marshal and unmarshal these XML documents using the Default Namespace Remapping technique by:
defining the default namespace for the types with no namespace:
com.sun.xml.internal.bind.defaultNamespaceRemap property (JDK JAXB >=JDK 1.8)
com.sun.xml.bind.defaultNamespaceRemap property (External JAXB JDK 1.9+)
performing marshalling/unmarshalling as usual
Here’s the code that is responsible for that (JDK 1.8):
//Initialize JaxbContext
Map<String, String> properties = new HashMap<>();
properties.put("com.sun.xml.internal.bind.defaultNamespaceRemap", "partC");
JAXBContext jaxbContext = JAXBContext.newInstance(new Class[]{SomeType1.class}, properties);
//Unmarshall Message object file from example XML
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Object messageObject = unmarshaller.unmarshal(getClass().getResourceAsStream("/example/chameleon/Division.xml"));
//Marshall message object back into XML
ByteArrayOutputStream xmlMessageOS = new ByteArrayOutputStream();
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.marshal(messageObject, xmlMessageOS);
System.out.println(xmlMessageOS.toString());
//Validate output XML with schema
InputStream xmlInputStream = new ByteArrayInputStream(xmlMessageOS.toByteArray());
Source xmlSource = new StreamSource(xmlInputStream);
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(getClass().getResource("/example/chameleon/PartC.xsd"));
Validator validator = schema.newValidator();
validator.validate(xmlSource);`
Unfortunately, You have to use different JAXB contexts for JAXB objects coming from PartA and PartC namespaces. This is required because JAXB default namespace remapping property is set per JAXB context - this way JAXB marshaller/unmarshaller knows how to deal with POJO objects that have no namespace defined (PartB).
Nevertheless, I do not think it is problematic as usually all the JAXB contexts are initialized once - during the application startup (in singleton).
To sum up, the workaround described above allows You to use JAXB to marshall/unmarshall XML documents without modifying the chameleon schemas. The proxy XSD file is used only at the beginning - for the process of generating JAXB objects (XJC). The marshalled/unmarshalled XML documents still conform to the original schemas. This technique is useful especially if You are not allowed to modify the schemas. I was dealing with that problem for read-only NDC standard (set of schemas) in 18.1 version defined by http://www.iata.org.
I've written an article on that topic: How to deal with Chameleon namespace design in JAXB. You will find it here: https://medium.com/#pziobron/how-to-deal-with-chameleon-namespace-design-in-jaxb-e36bcc03767d. Hopefully, You will find it useful.
Related
I implemented an xsd scanner, which creates an targetNamespace=<file.xsd> catalog.
Includes are filtered, so the catalog has only the root files of the targetNamespace.
With this catalog I'm resolving the required files (using a LSResourceResolver) to validate incoming xml files.
Map
namespace1=path/xsdForNameSpace1
namespace2=path/xsdForNameSpace2
:
But now I got multiple XSD, containing different content, but implementing the same targetNamespace.
Imho this is not correct, one namespace one root xsd - done
Example
schema1.xsd:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.xxxxxxx.com/texxxxxxx"
targetNamespace="http://www.xxxxxxx.com/texxxxxxx"
elementFormDefault="qualified">
<xsd:include schemaLocation="xxxxxx_xxxxxx_xxxxx_xxxxx.xsd"/>
<xsd:element name="ab120">
<xsd:complexType>
:
schema2.xsd:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.xxxxxxx.com/texxxxxxx"
targetNamespace="http://www.xxxxxxx.com/texxxxxxx"
elementFormDefault="qualified">
<xsd:include schemaLocation="xxxxxx_xxxxxx_xxxxx_xxxxx.xsd"/>
<xsd:element name="ab122">
<xsd:complexType>
:
I have two xml files are implementing the identical namespace http://www.xxxxxxx.com/texxxxxxx one with a root element ab120 the other with a root element ab122.
In this case my map contains only one of the implementing xsd files and I've no idea how to resolve the correct xsd for the incoming xml.
The incoming xml files look like this.
file1.xml:
<ab120 xmlns="http://www.xxxxxxx.com/texxxxxxx" ...>
:
</ab120>
file2.xml
<ab122 xmlns="http://www.xxxxxxx.com/texxxxxxx" ...>
:
</ab122>
The LSResourceResolver interface does not give me access to the xml, so I can't decide according the root node, which xsd I should use.
My temporary solution:
I added a second index with (namespace,xsd_file_name) that resolves correctly when the xml provides the implementing file (systemID)
targenNamespace="namespace myfile.xsd"
My question is, is it correct to specifiy multiple XSD file implementing the same namespace with different xsd structures ?
Edit:
It seemed to be not clear enough. Added two examples
My question is, is it correct to specifiy multiple XSD file implementing the same namespace with different xsd structures ?
Yes, that is a valid use of XML schema. A schema does not have to be represented by a single XSD file. Please see https://www.w3.org/TR/xmlschema-0/#SchemaInMultDocs and https://www.w3.org/TR/xmlschema-0/#import
You may also find this thread helpful: What's the difference between xsd:include and xsd:import?
Ok after asking w3c there is nothing in the specs that precludes this.
Reusing a targetNamespace with different content is allowed.
However, how to handle this, if you have to validate XMLs, is on your own and depends on the situation.
Possible solutions could be adding a version tag to the xml header or combine schemas if possible.
In my context nothing of the above would help, the resolver interface does not allow additional information, and the xsds can not be combined by a choice.
The only way to solve the issue is creating different index, resolver combinations. When creating the validator I have to use the correct resolver according to the origin where the xml came from.
How about including the two existing XSDs in a third one and use this for validation?
schema3.xsd:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema targetNamespace="http://www.xxxxxxx.com/texxxxxxx"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:include schemaLocation="schema1.xsd"/>
<xs:include schemaLocation="schema2.xsd"/>
</xs:schema>
We're facing an issue when marshalling an object to xml with JAXB. In our code example (https://github.com/fbe/JaxbIssueTracker, simple maven project, test-case demonstrates what's going wrong) we have three types:
parent
hijacked
concrete
XSDs can be found here: github
The parent type is abstract, concrete extends the parent, parent references the hijacked type in a sequence. From these xsd-files the JAVA files are being generated by JAXB (xjc) without any warn- or error-messages.
When marshalling a concrete type the following xml-output is being generated by JAXB:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns3:concreteType xmlns:ns2="http://www.felixbecker.name/parent" xmlns="http://www.felixbecker.name/hijacked" xmlns:ns3="http://www.felixbecker.name/concrete">
<ns2:hijacked>
<value>foobar</value>
</ns2:hijacked>
</ns3:concreteType>
As you can see the hijacked-type is falsely using the ns2-prefix which refers to the namespace of the parent type - but instead it should use the default namespace which refers to the hijacked namespace.
JAXB is not able to unmarshal this generated xml although it is generated by itself with activated schema validation.
What is going wrong here? Is the xml-schema broken? Or is JAXB not able to deal with inheritance correctly?
Removing the abstract-attribute from the parent.xsd did not have any effect on the faced issue.
Any help would be highly appreciated! :-)
Used versions (both broken):
JAXB from JDK 1.6
JAXB-RI 2.2.5
Regards,
fbe & ollinux
In your example, the hijacked element is actually defined in the parent schema and so gets placed in the "parent" namespace. This means the namespaces of the marshalled document are correct. If jaxb can unmarshal the document it itself marshalled then this sounds like a bug to me.
To get the hijacked element in the correct namespace you could move the element declaration to the hijacked schema and use
<element ref="hijacked:hijacked"/>
in the parent schema.
I am trying to work out how to unmarshall and XML document to a Java document.
The top of the xml document looks like this
<xs:myData xmlns:xs="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com example.xsd ">
There is a schema file whose top section looks like this:
<schema targetNamespace="http://www.example.com"
elementFormDefault="qualified"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xs="http://www.example.com">
I would like to unmarshall the xml document using Spring/JaxB and eventually convert it to a JPA object. I am not sure how to go about so i looked for examples on google and came up with this http://thoughtforge.net/610/marshalling-xml-with-spring-ws-and-jaxb/
I understand most of it except how or where the schema is used.
I have seen other examples where the schema is explicitly specified, i.e.
SchemaFactory schemaFac = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema sysConfigSchema = schemaFac.newSchema(
new File("example.xsd"));
unmarshaller.setSchema(sysConfigSchema);
RootElement root = (RootElement)unmarshaller.unmarshal(
new File("example1.xml"));
How is the schema shown in the first link used to validate the xml document?
Are there any disadvantages to using Spring's jaxb2Marshaller as opposed to direct use of JAXB?
What is the effect of having the namespace next to the XmlElement annotation? (See the Person class)
I would appreciate any more examples showing Spring/REST with unmarshalling with schema validation.
Thanks
As far as I know JAXB does not parse xsi attribute to dereference XSD, load it and use for validation. Perhaps that was done to disable automatic validation, otherwise it would be problematic to switch it off :)
Spring Jaxb2Marshaller was obviously added to implement the same interface org.springframework.oxm.Marshaller (which is implemented also by CastorMarshaller, JibxMarshaller, ...). It is very powerful and allows you to tune JAXBContext in very flexible way (I can't imagine the scenario when provided API is not enough). From pattern point of new Jaxb2Marshaller is a builder, so it does not add anything to core JAXB functionality. But there are some evident advantages. For example, schema loading is very simple. In the article the Spring context refers the person.xsd (<property name="schema" value="classpath:schema/person.xsd"/>) which one need to put into resources explicitly. Then JAXB marshaller/unmarshaller will use this schema to validate XML when XML is generated/loaded.
#XmlElement(..., namepsace="xxx") will automatically generate this XML element with a specified namespace. It's rare case if somebody does not use namespaces. I would say writing XSD without namespaces is not normal, as you want to avoid the element name collision.
Using JAXB with RestTemplate is very simple. You need to be sure that JAXB runtime is in your classpath (JDK 6 already has it) and your bean is annotated with #XmlRootElement. Then just use Person person = restTemplate.getForObject(restServiceUrl, Person.class),
I'm trying to generate some java code from the following WSDL: http://www.ebi.ac.uk/Tools/services/soap/emboss_needle?wsdl
$ wsimport -keep "http://www.ebi.ac.uk/Tools/services/soap/emboss_needle?wsdl"
however it generates some JAXBElement<String> instead of String. So I've tried to use a xjb binding as it is described here: Get rid of JAXBElement in classes generated by wsimport called from ant
<jxb:bindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
<jxb:bindings>
<jxb:globalbindings generateelementproperty="false">
<jxb:javatype name="java.lang.String" xmltype="xs:string"/>
</jxb:globalbindings>
</jxb:bindings>
</jxb:bindings>
but wsimport raises an exception:
$ wsimport -keep -b binding.xjb "http://www.ebi.ac.uk/Tools/services/soap/emboss_needle?wsdl"
[ERROR] The "jxb:globalbindings" customization is not associated with any schema element.
line 6 of file:/home/lindenb/tmp/WS/biostar14996.xjb
The XSD schema is embedded in the WSDL document. What URI should I give for the jxb:schemaLocation ? How can I fix that problem ?
Thanks,
P.
Eventually I ended up with:
<jxb:bindings version="2.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" wsdlLocation="YOUR_WSDL_LOCATION">
<jxb:globalBindings generateElementProperty="false"/>
</jxb:bindings>
The EMBL-EBI's EMBOSS needle service (http://www.ebi.ac.uk/Tools/services/soap/emboss_needle?wsdl), and most of their other analysis tool services (see http://www.ebi.ac.uk/Tools/webservices/) allow for submission parameters to have three states:
Explicit value
Null value
To be omitted
This provides compatibility with a wide range of SOAP tool-kits, some of which assume only one or two out of these three behaviors.
An unfortunate side-effect of this is that tool-kits such as JAX-WS, which understand that there are three states, need to use a more complex representation to handle this. Thus the JAXBElement classes are required. EMBL-EBI provides sample clients with source code using JAX-WS for their InterProScan (SOAP) and NCBI BLAST (SOAP) services, which use the same pattern for their parameters (see http://www.ebi.ac.uk/Tools/webservices/tutorials/06_programming/java/soap/jax-ws).
I believe your problem is similar to this post; there are links pointing you to the documentation, as well as the solution; basically, when you bind against WSDL files, you need a different top level element; the accepted response gives you the command line as well.
I have two schemas A and B with a circular dependency (it's an intermediate step). The XML files I'm using as input validate against the schema according to xmllint and Visual Studio. Eclipse is telling me that both schemas contain two global components with the same name.
A.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance"
targetNamespace="http://foo.org/A"
xmlns="http://foo.org/A"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">
<xs:import schemaLocation="b.xsd" />
B.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance"
xmlns:foo="http://foo.org/A"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">
<xs:import namespace="http://foo.org/A" schemaLocation="a.xsd" />
The XSD I'm passing to the Unmarshaller is A.xsd. When it encounters an element defined in B.xsd, it complains:
org.xml.sax.SAXParseException: cvc-elt.1: Cannot find declaration of element 'foo'.
I've set the schema via (pseudo):
InputStream in = .. A.xsd
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
return factory.newSchema(new StreamSource(in);
Can anyone explain what I'm doing wrong? Thanks.
<xs:import> is used to import namespaces defined in other schema into the current schema. The schemaLocation attribute is nothing more than a hint as to where to find that other namespace.
In the case of B.xsd, you're saying that you want to import the namespace http://blah.org, and that that namespace is handled by the schema in A.xsd.
In the case of A.xsd, your import of B.xsd is not specifying which namespace you're importing.
If A.xsd and B.xsd are representing different namespaces, then the import needs to specify that explicitly.
If, on the other hand, you're just trying to inline the elements from another schema file, in the same namespace, then the include directive is more appropriate.
edit: OK, having seen your schema fragments, I can say that <xs:import> is definitely not the right thing to do. Both A.xsd and B.xsd are defining elements in the same namespace (http://foo.org/A), and so you should be using <xs:include> instead.
When Java encounters an <xs:import>, and the namespace of that import is a namespace that it already knows about, then it effectively ignores it. So as it's parsing B.xsd (in namespace http://foo.org/A), and it finds an import for that same namespace, it ignores it.