XmlRootElement annotation at abstract class - possible? - java

This is what I'm trying to do:
#XmlRootElement(name = "bar")
#XmlAccessorType(XmlAccessType.NONE)
public abstract class Bar {
}
public final class Foo extends Bar {
#XmlElement
public String getMsg() {
return "hello, world!";
}
}
Now I'm trying to marshall an instance of class Foo:
com.sun.istack.SAXException2: unable to marshal type "Foo" as
an element because it is missing an #XmlRootElement annotation
What is a workaround?

Can you get away without the #XmlRootElement annotation on the superclass. Instead you should put it on each of your subclasses. JAX-B will still know about the superclass fields.

Related

Ignore JsonDeserializer when deserialising sub classes objects

I have parent class on which I have specified a custom deserialiser like this -
#JsonDeserialize(using = CustomDeserializer.class)
public class ParentClass {
}
I have subclasses extending above class and I don't want those classes to use CustomDeserializer for deserialisation purpose. I know using Will ignore the CustomDeserializer class during serialisation.
#JsonDeserialize(as = Child.class)
public class ChildClass extends ParentClass {
}
The question is - Is there any other way to tell ObjectMapper or anything else which will ignore this CustomDeserializer without specifically specifying #JsonDeserialize(as = Child.class) on every child class ?
Remove the annotation from the ParentClass and create a new subclass with the annotation. Use this new subclass when you want to deserialize to a ParentClass. As the custom deserialize annotation is on the subclass you can return an instance of ParentClass.
public class ParentClass {
// fields in the ParentClass
}
#JsonDeserialize(using = CustomDeserializer.class)
public class ParentWithCustomDeserialize extends Parent {
}
Then you can simply...
Parent parent = objectMapper.readValue(jsonString, ParentWithCustomDeserialize.class);

Jaxb custom element from two fields of an object

Is there a way with jaxb to create a custom element from two fields from an object?
Here's an example of what I have and what I want. I realize I could extract the fields into a seperate annotated class, but I'm curious of theres a way to do something similar to this.
#XmlRootElement()
public class Foo {
public String bar
public String baz
}
Expected output xml:
<foo>
<customElement bar="barValue">bazValue</customElement>
</foo>
Thanks!
class for foo
#XmlRootElement()
public class Foo {
private customElement CustomElement;
public CustomElement getCustomElement(){
return customElement;
}
#XmlElement
public void setCustomElement(CustomElement customElement){
this.customElement = customElement;
}
}
class for custom element
#XmlAccessorType(XmlAccessType.FIELD)
public class CustomElement {
#XmlAttribute
private String bar;
#XmlValue
private String baz
// set getters and setters
}

JAXB: Annotations of field declared in superclass differ in subclasses

I will try to explain the issue with an example:
Base:
public abstract class Base {
protected Foo foo;
}
Derived1:
//#SomeXMLAnnotations
public class Derived1 extends Base {
//Here i would like to define annotations for foo
#XmlElements({
#XmlElement(name = "foo1", type = Foo1.class),
#XmlElement(name = "foo2", type = Foo2.class)
})
//#AnyAnnoations..
//protected Foo foo;
}
Derived2:
//#SomeXMLAnnotations
public class Derived2 extends Base {
//Here i would like to define annotations for foo too
//But they will differ from the ones defined in Derived1
#XmlElements({
#XmlElement(name = "foo3", type = Foo3.class),
#XmlElement(name = "foo4", type = Foo4.class)
})
//#AnyAnnoations..
//protected Foo foo;
}
The #XmlElements annotation is just an example. It should work with any other annotation too.
I know I could shadow the superclass foo field but I dont think it's a proper way to solve this issue.
So is it possible in java (with JAXB) to override/add annotation of/to a field that is declared in a superclass?
"Ugly" solution:
//#SomeXMLAnnotations
public class Derived1 extends Base {
//#AnyAnnoations..
public Foo getFoo() {
return this.foo
}
protected Foo setFoo(Foo foo) {
this.foo = foo;
}
}
Overriding/adding properties and annotating them seems to work. If getter or setter is never used somewhere it's pretty ugly though, because this has to happen in every subclass.

JAXB abstract class with #XmlTransient

I'm using JAXB to unmarshal some xml into an object(s).
I have a class which inherit from an abstract class. I've marked the abstract class as #XmlTransient. Then using XMLType PropOrder I can access the properties in the abstract class like so:
#XmlType( propOrder = { "id"...
Cool. Problem is sometimes it isn't an element that I want to access but rather an attribute. Normally you would define such a property using #XMLAttribute to indicate the value is stored in an xml attribute and not an element. But given the fact that I've already used XMLTransient on the abstract class where 'id' is defined, JAXB complains when I try to mark the field as #XMLAttribute.
JAXB is complaining that I'm trying to access/return two fields of with the same name.
Can anyone please point me in the right direction? I'm building for GAE so I dn't really want to use any other libraries.
Thanks in advance!
Below are a couple of things you can do:
Java Model
Foo
You can annotate the property on the parent class with #XmlAttribute.
import javax.xml.bind.annotation.*;
#XmlTransient
public class Foo {
private String att1;
private String att2;
#XmlAttribute
public String getAtt1() {
return att1;
}
public void setAtt1(String att1) {
this.att1 = att1;
}
public String getAtt2() {
return att2;
}
public void setAtt2(String att2) {
this.att2 = att2;
}
}
Bar
You can override the property on the subclass and annotate it with #XmlAttribute.
import javax.xml.bind.annotation.*;
#XmlRootElement
public class Bar extends Foo {
#Override
#XmlAttribute
public String getAtt2() {
return super.getAtt2();
}
#Override
public void setAtt2(String att2) {
super.setAtt2(att2);
}
}
Demo Code
Demo
Here is some demo code you can run to show that everything works.
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Bar.class);
Bar bar = new Bar();
bar.setAtt1("a");
bar.setAtt2("b");
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(bar, System.out);
}
}
Output
Below is the output from running the demo code:
<?xml version="1.0" encoding="UTF-8"?>
<bar att1="a" att2="b"/>

jaxb: inline elements

Given:
#XmlRootElement(name = "foo")
class Foo {
public Bar getBar() {...}
}
class Bar {
#XmlElement(name = "string")
public String getString() {return "hello";}
}
How do I annotate so the XML will be:
<foo>
<string>hello</string>
</foo>
You could do the following leveraging the #XmlValue annotation.
Foo
#XmlRootElement
class Foo {
#XmlElement(name="string")
public Bar getBar() {...}
}
Bar
class Bar {
#XmlValue
public String getString() {return "hello";}
}
For More Information
http://blog.bdoughan.com/2011/06/jaxb-and-complex-types-with-simple.html
You probably need to use #XmlSeeAlso annotation on top of your class.
You can use #XmlSeeAlso annotation when you want another Entity bean to be included in the XML output. Can you try this in your Foo class
#XmlRootElement(name = "foo")
#XmlSeeAlso(Bar.class)
class Foo {
public Bar getBar() {...}
}
Update1:
For your comment to remove the bar tag in the XML try using EclipseLink JAXB (MOXy)'s. #XmlPath will solve your issue.
#XmlRootElement(name = "foo")
#XmlSeeAlso(Bar.class)
class Foo {
#XmlPath(".")
public Bar getBar() {...}
}
Refer here for more details.
I'm not sure you can to eliminate the tag bar from resulting XML:
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JAXBUsing4.html#wp148576

Categories