Generate additional custom method with jaxb-xjc - java

There's some way to generate a custom method within an class generated with JAXB.
I search around tutorials, including oracle's tutorial, but I didn't find clear instructions how can I custom methods to a generated class described on XML Schema.

I have found the following to be the best way to add custom behavior:
https://javaee.github.io/jaxb-v2/doc/user-guide/ch03.html#compiling-xml-schema-adding-behaviors
You can implement the custom behavior for a JAXB generated class BaseType in a custom class BaseTypeExt that extends the JAXB generated class BaseType.
You also tell JAXB to use your extended class BaseTypeExt (instead of the BaseType class it extends) as the base class for all classes that normally would have extended the BaseType class.
I used this successfully to override the toString() method in my generated class BaseType.
This seems simpler than writing an XJC plugin.

You can write an XJC plugin:
http://weblogs.java.net/blog/kohsuke/archive/2005/06/writing_a_plugi.html

Related

JAXB - trying to marshall a java object from external jar

I'm trying to marshall this class using jaxb
import com.vividsolutions.jts.geom.Point;
public class TaskPost {
...
Point point;
...
}
(with getters and setters)
Class point is imported from an external jar which i have no source code to, how can i manually marshal this?
I need to use specific methods to get the data from the point class (for now its printing one of the fields SRID>0/SRID> (which are html tags))
Any help would be appreciated.
A JAXB implementation does not require any annotations on a model class so it would apply the default mappings to it. Alternatively, you could write an XmlAdapter to convert Point to/from your own model class for the purpose of marshalling/unmarshalling.

How to handle various concrete implementations of an Interface with JAX-B

I have a class that any I need to marshal to XML.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class ClassToBeMarshalled {
public Interface object;
}
The Interface is implemented by a lot of concrete classes and most of them are vendor specific whose source code I don't have access to.
So my problem is:
If I try to marshal that class, JAX-B will complain that the current concrete implementation of Interface is not known in the context - In another words, the concrete class was not loaded into the context by calling JAXBContext.newInstance providing the current implementation.
The most common ways to sort out that problem are:
1) Use XMLSeeAlso - not a viable option as there are a lot of concrete classes
2) Annotate each class with #XmlRootElement - not a viable option as I don't have access to all the classes
Does anyone know a way to make JAX-B load the concrete class into its context as the need arises?
Thanks.
P.S.: I'm using JAX-B RI
You could mark your object as #XmlAnyElement(InterfaceHandler.class) where InterfaceHandler is a DomHandler capable of translating between a DOM representation and the actual implementing classes. That handler should probably store the class name when marshalling, and use that class name to create the instance when unmarshalling. It might either configure the instance manually, perhaps using some helper classes designed to work with beans, or it might use another jaxb context which includes that specifically named class and will handle that object with all its nested children.
Also have a look at the #XmlElementRef annotation. I fear that in order to make this work properly, you'd have to at least know all the implementing classes at compile time, but perhaps there is a way you can make this work for you as well, with less trouble than the generic solution outlined in the previous paragraph.

Possible to use the #XmlSeeAlso dyncamiclly?

Instead of this
#XmlSeeAlso({User.class,Role.class,Function.class})
I would like something like this:
#XmlSeeAlso(Access.getWebServiceClasses())
Is it possible?
I want this since my webservice just contains interfaces and if I change the implementation I would just like to change in my factory so it returns the right classes instead of having to change in the webservice itself.
This isn't possible, since annotation elements must be simple types (strings, primitives or classes (see annotations).
It is possible however (in CXF) to override org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.getExtraClass() method which, by default checks #XmlSeeAlso of the interface. My implementation returns additional ObjectFactory classes.
Chances are that you're using <jaxws:endpoint /> in CXF's Spring XML configuration. To be able to override this method, you have create few classes:
org.apache.cxf.jaxws.spring.EndpointDefinitionParser must use class derived from org.apache.cxf.jaxws.spring.EndpointDefinitionParser.SpringEndpointImpl (when using JAXWS 2.1) or from org.apache.cxf.jaxws22.spring.JAXWS22SpringEndpointImpl (JAXWS 2.2)
This class must call super.setServiceFactory() passing org.apache.cxf.jaxws.support.JaxWsServerFactoryBean with overriden getExtraClass()
You have to provide your own org.apache.cxf.jaxws.spring.NamespaceHandler (you can create derived class) for your own namespace (e.g. http://cxf.apache.org/jaxws/dynamic) which will register your own parser for jaxws:endpoint element:
registerBeanDefinitionParser("endpoint", new EndpointDefinitionParser());
(sorry, I can't provide full example - I'm writing from memory and CXF's source code)

JAXB 2.0 - how to marshal static inner classes

In JAXB 2.0 if you compile a schema to java classes and a class contains an inner class, are you required to do anything different while building your content tree from the generated classes?
If so, what?
Thanks!
I don't think it requires any special treatment.

Marshalling arraylist of abstract class in JAXB

I have a Java application that I want to save the data in XML instead of a database.
We decided to go with JAXB and instead of generating files based on the schema, we just added annotations to our Java files.
The issue we are running into is that we have an ArrayList of an abstract class called Node. A Node has subclasses of either Module or ScreenImage. When we marshall the arraylist, it doesn't save the type. Such as:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Module"
Does JAXB support elements that are abstract?
How do I get JAXB to save the type, so that I'm able to unmarshall it?
axtavt's suggestion is fine. I just want to add another approach. You could make use of #XmlSeeAlso, where you can declare other classes that should defined and visible to JAXBContext. You only have to make sure to declare the annotation within a class that is already visible to JAXBContext.
e.g.:
#XmlRootElement
#XmlSeeAlso({Node.class, Module.class, ScreenImage.class})
class SomeContent {
private List<Node> nodes;
///... accessors
}
It should work fine.
Note that if your Module and ScreenImage are not statically accessible from the bound classes (i.e. the classes specified in JAXBContext.newInstance(...)), they should be bound explicitly (add them to the JAXBContext.newInstance(...) parameters).

Categories