I have a sample XML as shown below:
<?xml version="1.0" encoding="UTF-8"?>
<Education>
<School name="ABC" location="Mangalore">
<Student gender="M" housepincode="575020">
<FirstName>VJ</FirstName>
<LastName>K</LastName>
</Student>
<Student gender="M" housepincode="575002">
<FirstName>S</FirstName>
<LastName>K</LastName>
</Student>
</School>
</Education>
This has been unmarshalled with the help of JAXB using the following approach. I have classes for Education,School and Student.
Education.java
import lombok.Data;
@Data
@XmlRootElement(name = "Education")
public class Education {
public School School;
}
School.java
import lombok.Data;
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class School {
@XmlAttribute
private String name;
@XmlAttribute
private String location;
@XmlElement(name ="Student")
private List<Student> Student;
}
Student.java
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class Student {
@XmlAttribute
private String gender;
@XmlAttribute
private String housepincode;
@XmlElement(name = "FirstName")
private String FirstName;
@XmlElement(name = "LastName")
private String LastName;
}
I have some concerns over the output I receive. First of all there are some warnings. I believe it is because i have missed some annotations which should be present. Any suggestions or guidance here please?
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.sun.xml.bind.v2.runtime.reflect.opt.Injector (file:/C:/Users/R.Premsagar/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.0-b170127.1453/jaxb-runtime-2.3.0-b170127.1453.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int)
WARNING: Please consider reporting this to the maintainers of com.sun.xml.bind.v2.runtime.reflect.opt.Injector
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Education(School=School(name=ABC, location=Mangalore, Student=[Student(gender=M, housepincode=575020, FirstName=VJ, LastName=K), Student(gender=M, housepincode=575002, FirstName=S, LastName=K)]))
Also, the heirarchy of output does not seem correct to me, Eg: School = School tag? I want to print this output to a separate XML to verify the result. However the script fails
Main program:
List<Education> Entries = new ArrayList<Education>();
try {
File xmlFile = new File("Withattributes.xml");
JAXBContext jaxbContext;
jaxbContext = JAXBContext.newInstance(Education.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Education entries = (Education) jaxbUnmarshaller.unmarshal(xmlFile);
Entries.add(entries); //storing objects in a list for later use
//--------------------------------------------------------------
JAXBContext jaxbContext_w = JAXBContext.newInstance(Education.class);
Marshaller jaxbMarshaller = jaxbContext_w.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
jaxbMarshaller.marshal(jaxbContext_w, System.out);
}
catch (JAXBException e)
{
e.printStackTrace();
} catch (FactoryConfigurationError e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I get the following error message:
Neither the class com.sun.xml.bind.v2.runtime.JAXBContextImpl nor one of the associated superclasses is known to this context.
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:593)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:482)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:328)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:256)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:110)
at JaxbExample.main(JaxbExample.java:39)
Please let me know what could be done here..
UPDATE:
If the XML is updated to have a structure as below:
<?xml version="1.0" encoding="UTF-8"?>
<Education>
<School name="ABC" location="Mangalore">
<Student gender="M" housepincode="575020">
<FirstName>VJ</FirstName>
<LastName>K</LastName>
<Hobbies>
<Hobby time = "M">Novels</Hobby>
<Hobby time = "A">Gaming</Hobby>
</Hobbies>
</Student>
</School>
</Education>
Now the class of Student.java would change to
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class Student {
@XmlAttribute
private String gender;
@XmlAttribute
private String housepincode;
@XmlElement(name = "FirstName")
private String FirstName;
@XmlElement(name = "LastName")
private String LastName;
@XmlElementWrapper(name ="Hobbies")
@XmlElement(name="Hobby")
private List<Hobby> Hobbies;
}
and the Hobby.java
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class Hobby{
@XmlAttribute(name="Time")
private String Time;
@XmlElement
private String Hobby;
}
With this modification I do not get the value of the Hobby tag. I get the list of Hobbies and values something like this:
Hobbies>
<Hobby time = "M"/>
<Hobby time = "A"/>
</Hobbies>
Could you correct me here please?