How to write the JAXB object that has attribute and value - java

Here's my intended XML structure
<Outer type="good" id="1">
<Uid>123</Uid>
<Name>Myself</Name>
<Inner type="bad">This Value</Inner>
</Outer>
Here's my Object.
#XmlAccessorType(XMLAccessType.FIELD)
#XmlType(name="Outer", propOrder = {
"uid"
"name"
"inner"
})
public class Outer{
#XmlElement(name = "Uid")
protected String uid;
#XmlElement(name = "Name")
protected String name;
#XmlElement(name = "Inner")
protected Inner inner;
public static class Inner{
#XmlAttribute
private String type;
#XmlValue
private String value;
//setters & getters for both
}
//setters & getters for all the elements
}
Now in my class I am doing
Outer o = new Outer();
o.setUid/ID/Type/Name() ; //all the setter
Inner i - new Inner();
i.setValue("This Value");
i.setType("bad");
When Irun this i am getting
If a class has #XmlElement property, it cannot have #XmlValue property.
And
Class has two properties of the same name "type" (This one is for the Source class)
And
Class has two properties of the same name "value" (This one is for Source class too)
What is happening, and what I can I do rectify this?
Thanks

Currently, JAXB threats both fields (due to annotations) and both pairs of get/set (due to default accessor type) as properties. So you class Inner has 4 properties.
Please, add own accessor type for Inner class
#XmlAccessorType(XmlAccessType.FIELD)
public static class Inner
{
Or annotate properties instead of fields
public static class Inner
{
private String type;
private String value;
#XmlAttribute
public String getType()
{
return type;
}
// setter setType
#XmlValue
public String getValue()
{
return value;
}
// setter setValue
}

Add XmlRootElement annotation to the Outer class, besides of that it shoud work.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Outer", propOrder = {"uid", "name", "inner"})
public static class Outer {

Related

JAXB how to nest several objects?

I've been trying to search how to do this but I haven't found an answer to my exact requirements:
Let's say we had this 3 classes:
public class Main {
public ArrayList<MyFirstClass> myFirstClass;
}
class MyFirstClass {
public int num;
public MySecondClass mySecondClass;
}
class MySecondClass {
public String otherStr;
public MyThirdClass myThirdClass;
}
class MyThirdClass {
public int otherNum;
}
I wanto to be able to read these XML with the unmarshaller:
<Main>
<MyFirstClasses>
<MyFirstClass>
<num>1</num>
<MySecondClass>
<str>Hello</str>
<MyThirdClass>
<otherNum>2</otherNum>
</MyThirdClass>
</MySecondClass>
</MyFirstClass>
<MyFirstClasses>
</Main>
Where I'm basically able to set the variables that are objects (MySecond/Third Class).
I know I can use #XMLRootElement and then #XmlElementWrapper(name="aName") and #XmlElement(name="aName") to do the
<Main>
<MyFirstClasses>
<MyFirstClass>
<num>1</num>
</MyFirstClass>
<MyFirstClasses>
</Main>
But how can I then nest the MySecondClass inside MyFirstClass so I can set it's values, because otherwise the FirstClassObject will have a MySecondClass which has null values.
Thanks in advance!
The problem is that your xml does not match your POJOs. You can use annotations to fix this(renaming fields would also work). Try this:
#XmlRootElement(name = "Main")
public class Main {
#XmlElementWrapper(name = "MyFirstClasses")
#XmlElement(name = "MyFirstClass")
private List<MyFirstClass> myFirstClass;
}
Then FirstClass:
#XmlAccessorType(XmlAccessType.FIELD)
public class MyFirstClass {
private int num;
#XmlElement(name = "MySecondClass")
private MySecondClass mySecondClass;
}
And MySecondClass:
#XmlAccessorType(XmlAccessType.FIELD)
public class MySecondClass {
private String str;
#XmlElement(name = "MyThirdClass")
private MyThirdClass myThirdClass;
}
Finally MyThirdClass:
#XmlAccessorType(XmlAccessType.FIELD)
public class MyThirdClass {
public int otherNum;
}

JAXB unmarshal child attributes without creation of child class

I want to unmarshal a (simplified) XML structure like this:
<parent>
<a>AValue</a>
<b>BValue</b>
<c someAttribute = "true">CValue</c>
</parent>
I know how to do this with declaring a class C like this:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "c", propOrder = {
"someAttribute"
})
public class C{
#XmlValue
private String c;
#XmlAttribute ( name="someAttribute")
private boolean someAttribute;
//getters and setters
}
And getting it as a member in class parent like this:
public class Parent{
private String a;
private String b;
private C c;
//getters and setters for c,b,a
}
This works finde and i can access the value of C via parent.getC().getC();
My Question is how to achieve that i do not have to create a class C and get the value and attribute of C as a member of parent, without editing the parent Pojo with new members and other getters and setters.
I already tried to do this via Listeners and searched for similar structures, but i haven't got any ideas left.
I finally figured out how to achieve this.
Its necessary to use the #XmlJavaTypeAdapter Annotation and mark the C class as an #XmlRootElement as well as an #XmlAccessorType(XmlAccessType.FIELD).
Furthermore one need to use the #XmlTransient on the getter of the String member which was annotated with #XmlJavaTypeAdapter.
Full solution:
Class C:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class C{
#XmlValue
private String c;
#XmlAttribute
private boolean someAttribute;
//getters and setters for both
Class Adapter:
public class Adapter extends XmlAdapter<C, String> {
public String unmarshal(C pC) throws Exception {
//some possible handling with the attribute over pC.getSomeAttribute();
return pC.getC();
}
public C marshal(String pC) throws Exception {
C c = new C();
c.setC(pC)
//some possible handling to set the attribute to c
return c;
}
Class Parent:
public class Parent{
private String a;
private String b;
#XmlJavaTypeAdapter(Adapter.class)
private String c;
#XmlTransient
public String getC() {
return c;
}
//getters and setters for b,a and setter for C
}

How to pass a variable from 2 different POJOs?

I got 2 POJOs that are being passed to a HttpEntity and converted to json.
Before passing them i need a variable which is in both of the POJOs with different names because of the needs of the API so i cant change them.
What is the best way without casting and in terms of OOP also within the POJO definition like mentioned in Wikipedia?
Abstract pojo
public abstract class Pojo{
//some common variables
//setter getters
}
PojoOne
public class PojoOne extends Pojo{
private String id;
//setter getter for id
}
PojoTwo
public class PojoTwo extends Pojo{
private String identifier;
// setter getter for identifier
}
Class that
public class SomeOtherClass {
public void getIdForUse(Pojo pojo){
String s = pojo. // How should this be to have ability to get both id and identifier
}
}
Add a common method to the common superclass:
public abstract class Pojo {
public abstract String getId();
// some common variables
// setter getters
}
public class PojoOne extends Pojo {
private String id;
#Override
public String getId() {
return id;
}
//setter for id
}
public class PojoTwo extends Pojo {
private String identifier;
// setter getter for identifier
#Override
public String getId() {
return identifier;
}
}

com.sun.istack.SAXException2: class java.util.ArrayList nor any of its super class is known to this context

I am validating my request with XSD. In my request I set my content as List <Attribute>.
Attribute is a POJO:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "attribute", propOrder = {
"name",
"value"
})
public class Attribute {
#XmlElement(required = true)
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlSchemaType(name = "NCName")
protected String name;
#XmlElement(required = true)
protected Object value;
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
My validation fails with exception:
Caused by: javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.SAXException2: class java.util.ArrayList nor any of its super class is known to this context.
How to pass List<POJO> for validation ??
you can create a wrapper for this list
#XmlRootElement(name="attributes")
#XmlAccessorType(XmlAccessType.Field)
public class{
#XmlElement(name="attributes")
private List<Attribute> attributes;
public void setAttributes(List<Attribute> attributes){
this.attributes=attributes;}
public List<Attribute> getAttributes(){
return this.attributes;}
}
to validate the list of attributes you pass the list of attributes to this wrapper and jaxb will do the rest , we need this class because the parser doesn't accept classes not annotated with xmlRootElement and ArrayList and all its super classes are not annotated with xmlRootElement
java.util.ArrayList nor any of its super class is known to this context

#XmlElement and #XmlAccessorType(XmlAccessType.FIELD)

I have a strange behaviour, and I don't understand it.
#XmlRootElement
public class Object {
#XmlElement(name = "object")
private List<Object> objectList = new ArrayList<Object>();
public List<Object> getObjectList() {
return objectList;
}
}
This part should hold values for each object.
#XmlAccessorType(XmlAccessType.FIELD)
public class Object {
#XmlElement
private int id;
private int value;
}
I don't understand why are there values passed into the id and value fields. Is it necessary to write #XmlElement if the names are the same?

Categories