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.
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.
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.
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.
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).
How is it possible to make some xjc generated classes subclasses of a custom Exception, such that you can actually throw them, and processable by the JAXBContext? Often webservices return various faults defined that really should be an exception, but since they aren't you need to wrap them unneccesarily.
Even if you could create a JAXB (JSR-222) model that extended from Exception you wouldn't be able to create a JAXBContext from it. I would recommend wrapping the Exception in a domain model that is compatible with JAXB.
Java Model (Foo)
Below is a simple Java class that extends Exception.
package forum12840627;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Foo extends Exception {
}
Demo
The demo code below attempts to creates a JAXBContext on the Java model.
package forum12840627;
import javax.xml.bind.JAXBContext;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Foo.class);
}
}
Output
Below is the exception returned from running the demo code. The problem is that Exception is not a valid JAXB class and JAXB implementations pull in the super classes as it processes the Java model. (Note: In your own domain model you can annotate super classes with #XmlTransient to prevent them from being processed: http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html)
Exception in thread "main" com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.lang.StackTraceElement does not have a no-arg default constructor.
this problem is related to the following location:
at java.lang.StackTraceElement
at public java.lang.StackTraceElement[] java.lang.Throwable.getStackTrace()
at java.lang.Throwable
at java.lang.Exception
at forum12840627.Foo
at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:102)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:472)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:302)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1140)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:154)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:121)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:202)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:363)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:522)
at forum12840627.Demo.main(Demo.java:8)
UPDATE #1
If you are using EclipseLink JAXB (MOXy) as your JAXB provider then you will not see this exception as classes in the javax.* and java.* packages are not treated as domain classes. MOXy is the default JAXB provider in the WebLogic 12c environment or can be configured using a jaxb.properties file.
For More Information
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
http://blog.bdoughan.com/2011/12/eclipselink-moxy-is-jaxb-provider-in.html
UPDATE #2
The latest versions of the JAXB reference implementation appear to handle this use case now as well as MOXy. My original portability concerns may not be so much of an issue.
Yeah, I finally found something! The Inheritance plugin is able to make the generated classes inherit from classes or implement additional interfaces.
You need to include something like
<bindings node="//xsd:complexType[#name='WhateverException']">
<inheritance:extends>foo.bar.WhateverException</inheritance:extends>
</bindings>
into the binding file and override getStackTrace() to return null such that it doesn't get marshalled.
Unfortunately you might run into trouble with some JAXB implementations (see Blaise Doughan's answer) - I haven't found a workaround for that yet. So you can either use a not quite nonportable solution, or wrap the JAXB objects into Exceptions.