JAXBContext, jaxb.properties and moxy - jaxb

The jaxb.properties needs to be in the same package as the domain classes you are creating the JAXBContext on.
I am using Moxy's xml driven configuration since I doesn't want to use annotations or XJC generated objects. I have an existing domain classes that are spread across multiple packages. Does this mean that i need to have the jaxb.properties present in all those packages or there is a better alternative (Maybe writing my own implementation of some interface that can read from a jvm arg or something)?

Does this mean that i need to have the jaxb.properties present in all
those packages?
If you are creating your JAXBContext on classes, then you need to have a jaxb.properties file in at least one of the packages of the domain classes passed in. In the example below you could have a jaxb.properties file in either package1 or package2.
JAXBContext jc = JAXBContext.newInstance(package1.Foo.class, package2.Bar.class);
If you are creating your JAXBContext on package names, then you need to have a jaxb.properties files in at least one of the packages. Note that packages are separated by a ':'.
JAXBContext jc = JAXBContext.newInstance("package1:package2");
or there is a better alternative
My preference is to use the standard JAXB APIs with a jaxb.properties file to specify MOXy as the JAXB provider. Some people prefer using the native MOXy APIs to do this:
JAXBContext jc = org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(new Class[] {Foo.class, Bar.class}, null);
For More Information
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html

Related

There's no ObjectFactory with an #XmlElementDecl for the element

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.

JAXB marshalling in Apache Camel

I am new to Apache camel and need to perform a task where I need to marshal an object to XML file. I am using the below code but it is not working. Here, foo.pojo is package where JAXB annotated classes are present
JaxbDataFormat jaxbDataFormat = new JaxbDataFormat("foo.pojo");
from("direct:start").marshal(jaxbDataFormat).to("file:C:/Users/Anand.Jain/Desktop/hello/abc.xml").end();
Option 1: Configure the context path
JaxbDataFormat jaxbDataFormat = new JaxbDataFormat("foo.pojo");
OptionFactory or jaxb.index file must be defined in the given package as explained here.
Option 2: Configure the class(es) to be bound
JAXBContext jaxbContext = JAXBContext.newInstance(MyAnnotatedClass.class);
JaxbDataFormat jaxbDataFormat = new JaxbDataFormat(jaxbContext);
I prefere Option 2.
Option 1 is recently impossible as JaxbDataFormat(String) constructor is not available as you can see in official javadoc
Documentation seems to be outdated about this point.
EDIT: BE CAREFUL there's TWO JaxbDataFormat
I have understood: there's TWO jaxbDataFormat in camel ecosystem
one is in camel-core package org.apache.camel.model.dataformat
another in camel-jaxb package org.apache.camel.converter.jaxb

One class in same package does not bind to JAXB context

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.

JAXB: classes generated by JAXB not recognised in context

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).

JAXB Unable To Handle Attribute with Colon (:) in name?

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.

Resources