I am using spring ws to implement my web service.
I am getting the following error in web service
"There's no ObjectFactory with an #XmlElementDecl for the element test"
test is having a #XmlElementRef.
While creating the jaxb context I have used ContextPath set to the package name.
I have done the following things:
Used xjc parse to convert from WSDL to pojos.
I had multiple WSDL's so the ObjectFactory was getting overwritten. So I just renamed the objectfactory prefix with WSDL. A.wsdl will have AObjectFactory etc. So I dont have any ObjectFactory class.
I think when looking for #XmlElementDecl it looks for "ObjectFactory" class and then it cant find it, bcoz if I rename my AObjectFactory to ObjectFactory this works.
My question is:
Can #XmlElementRef not refer to renamed object factory created by me?
Can #XmlElementRef be avoided somehow?
Can we have multiple ObjectFactories?
Also how does #XmlElementRef and #XmlElementDecl works if we do not create ObjectFactories at all.
Any help will be great.
While creating the jaxb context I have used ContextPath set to the
package name.
When you create a JAXBContext by context path, the JAXB implementation is going to look for a class called ObjectFactory that is annotated with #XmlRegistry.
I had multiple WSDL's so the ObjectFactory was getting overwritten.
Generally there should be one ObjectFactory per namespace/package. If the ObjectFactory was getting overwriiten perhaps you were trying to force everything to the same package name.
So I just renamed the objectfactory prefix with WSDL. A.wsdl will have
AObjectFactory etc. So I dont have any ObjectFactory class.
When the class annotated with #XmlRegistry is called something other than ObjectFactory you need to either:
Include a text file called jaxb.index in the same package as your domain model that contains the short name of all your classes in that package annotated with #XmlRegistry.
Bootstrap the JAXBContext of the generated classes annotated with #XmlRegistry.
Related
I defined objects with XSD model and I used Jaxb to create corresponding classes, to be able to load XML files on instance of classes and to generate XML files from instance of classes.
My elements defined on the XSD model are complex with several hierarchical level, using list, ID and IDREF.
One command of my program is to duplicate elements.
I can't use the clone method cause classes of element are generated by JAXB.
So i have tried to do deep copy with BeanUtils.cloneBean, next with SerializationUtils.clone from Apache but both methods don't work correctly with all my objects because of their complexity.
I found a solution that work, using JAXB to create a clone unmarshalling my element :
public ObjectXML duplicate(ObjectXML objectXML) throws JAXBException {
JAXBContext sourceJaxbContext = JAXBContext.newInstance(objectXML.getClass());
JAXBContext targetJaxbContext = JAXBContext.newInstance(objectXML.getClass());
Unmarshaller unmarshaller = targetJaxbContext.createUnmarshaller();
ObjectXML objectCopy = (ObjectXML) unmarshaller.unmarshal(new JAXBSource(sourceJaxbContext, objectXML));
return objectCopy;
}
ObjectXML is my parent class from all elements generated by JAXB. All elements inherit directly or indirectly from this class.
This method work fine except with IDREF attributes that link to another object : JAXB don't know the element that have the corresponding ID when I unmarshall an individual object, so it assign null to the attribute.
Have someone a solution to keep IDREF on the copy when linked object are not supplied to the unmarshal of JAXB?
Thank you for advance.
Few hints.
Try the copyable plugin from JAXB2-Basics. This plugin generates deep reflection-free copying methods which handle JAXB structures very well, and you can also specify your own copying strategy. Disclaimer: I'm the author.
Implement and register your own IDResolver, see this blog post. This would allow you to plug your own ID resolution strategy.
Using JAXBContext.newInstance("com.jaxbgen") to bind classes in this package.
And then use this context to create mashaller.
It's so strange that one entity class xxx in this package could not mashaller, and throw JAXBException nor any of its super class is known to this context.
And the other works well.
I try to use JAXBContext.newInstance(xxx.class) to initial the context, it works well.
But I need to use package name to mashaller all classed in this package.
Could anyone help me on it?
When the package name is used to create a JAXBContext the JAXB impl does one of the following:
Looks for a class called ObjectFactory and then transitively pulls in all reference ed classes.
Looks for a text file called jaxb.index which contains a carriage return separated list of short class names (not package qualified). These classes and all referenced classes are the processed.
JAXBContext context = JAXBContext.newInstance( "com.example.abcd", ObjectFactory.class.getClassLoader());
if i run this, i am getting error that ""com.example.abcd" doesnt contain ObjectFactory.class or jaxb.index"
But this package has ObjectFactory class. I am just wondering why this is showing me the error.
You need to ensure the ObjectFactory class is annotated with #XmlRegistry.
I am encountering this problem. Is there a fix somewhere?
Here is my file structure:
package jaxb_conainer_class;
package loader_class;
Main.java imports both loader_class and jaxb_conainer_class;
In the loader_class, a call to
JAXBContext context = JAXBContext.newInstance(xxxx.class);
gives me the crash above
Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
There's no ObjectFactory with an #XmlElementDecl for the element {}default.
When you generate classes from an XML schema you should create the JAXBContext on the generated package name. This will ensure that the ObjectFactory and everything else will be picked up correctly.
JAXBContext jc = JAXBContext.newInstance("com.example.foo");
If there are more than one package than you can use : as the delimiter.
JAXBContext jc = JAXBContext.newInstance("com.example.foo:org.example.bar");
Alternatively you can include the ObjectFactory class in the classes used to bootstrap the JAXBContext, but my recommendation is to use the package name(s).
I am attempting to use JAXB to unmarshall an XML files whose schema is defined by a DTD (ugh!).
The external provider of the DTD has specified one of the element attributes as xml:lang:
<!ATTLIST langSet
id ID #IMPLIED
xml:lang CDATA #REQUIRED
>
This comes into the xjc-generated class (standard generation; no *.xjb magic) as:
#XmlAttribute(name = "xml:lang", required = true)
#XmlJavaTypeAdapter(NormalizedStringAdapter.class)
protected String xmlLang;
However, when unmarshalling valid XML files with JAXB, the xmlLang attribute is always null.
When I edited the XML file, replacing xml:lang with lang and changed the #XmlAttribute to match, unmarshalling was successful (i.e. attributes were non-null).
I did find this http://old.nabble.com/unmarshalling-ignores-element-attribute-%27xml%27-td22558466.html. But, the resolution there was to convert to XML Schema, etc. My strong preference is to go straight from an un-altered DTD (since it is externally provided and defined by an ISO standard).
Is this a JAXB bug? Am I missing something about "namespaces" in attribute names?
FWIW, java -version = "build 1.6.0_20-b02" and xjc -version = "xjc version "JAXB 2.1.10 in JDK 6""
Solved the issue by changing replacing xml: with a namespace declaration in the JAXB-generated class:
#XmlAttribute(name = "lang", namespace="http://www.w3.org/XML/1998/namespace", required = true)
Which makes sense, in a way.
Without this kind of guidance, how would JAXB know how to interpret the otherwise-undefined namespace xml:? Unless, of course, it implemented some special-case internal handling to xml: as done in http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamReader.html#getNamespaceURI%28java.lang.String%29 (see the first NOTE:)
Whether it's a bug in xjc's generation of the annotated objects or a bug in the unmarhaller, or simply requires a mapping somewhere in the xjc process is still an open question in my mind.
For now, it's working and all it requires is a little xjc magic, so I'm reasonably happy.
Disclaimer: Although 8 years late, I am adding this answer for lost souls such as myself trying to understand auto generation of java files from a DTD.
You can set project wide namespaces for the unmarshaller to work with directly in the project-info.java file via the #XmlSchema option.
This file should be automatically generated by xjc when generating classes from a schema, however it appears xjc does not automatically generate the package-info.java file when generating from a DTD!
However, you can manually make this file, and add it to the same package as the files generated by xjc.
The file would look like the following:
package-info.java :
#XmlSchema(
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns = {
#XmlNs(prefix="xlink", namespaceURI="http://www.w3c.org/1999/xlink"),
#XmlNs(prefix="namespace2", namespaceURI="http://www.w3c.org/1999/namespace2")
})
package your.generated.package.hierarchy;
import javax.xml.bind.annotation.*;
You can add as many namespaces as required, simply add a new line in the form:
#XmlNs(prefix="namespace", namespaceURI="http://www.uri.to.namespace.com")
The benefit of doing it this way, rather than compared to editing the generated #XmlAttribute is that you do not need to change each generated XmlAttribute, and you do not need to manually remove the namespaces from the XmlAttribute name variable.