Error in converting XML containing attribute values to Java Object - java

I need to Unmarshal XML to Java Object, I have tried with below code but it is giving exception-
Main Class-
JAXBContext context = JAXBContext.newInstance(SimpleBean.class);
Unmarshaller unMarshaller = context.createUnmarshaller();
File file = ResourceUtils.getFile("classpath:config/SimpleBean.xml");
SimpleBean param = (SimpleBean) unMarshaller.unmarshal(new FileInputStream(file));
LOGGER.info("param: "+param.getRoot());
SimpleBean.java
#JsonIgnoreProperties(ignoreUnknown=true)
public class SimpleBean {
#JsonProperty("root")
private Root root;
public Root getRoot() {
return root;
}
public void setRoot(Root root) {
this.root = root;
}
}
Root.java
public class Root {
#JsonProperty("Schedule")
private List<Schedule> schedule;
public List<Schedule> getSchedule() {
return schedule;
}
public void setSchedule(List<Schedule> schedule) {
this.schedule = schedule;
}
}
Schedule.java
#JsonIgnoreProperties(ignoreUnknown=true)
public class Schedule {
#JsonProperty("ID")
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
SimpleBean.xml
<root>
<Schedule ID="561"></Schedule>
<Schedule ID="562"></Schedule>
</root>
Exception coming-
javax.xml.bind.UnmarshalException: unexpected element (uri:"",
local:"root"). Expected elements are (none)

You need to define an #XmlRootElement like this:
#XmlRootElement(name="root")
public class Root {
#JsonProperty("Schedule")
private List<Schedule> schedule;
public List<Schedule> getSchedule() {
return schedule;
}
public void setSchedule(List<Schedule> schedule) {
this.schedule = schedule;
}
}
Also, you don't need another wrapper POJO (SimpleBean).
You should do this directly (otherwise you'll get ClassCastException):
Root param = (Root) unMarshaller.unmarshal(new FileInputStream(file));
LOGGER.info("param: "+param);

This is a working solution-
SomeRoot.java-
#XmlRootElement(name="root")
public class SomeRoot{
private List<Schedule> schedule;
#XmlElement(name = "Schedule")
public List<Schedule> getSchedule() {
return schedule;
}
public void setSchedule(List<Schedule> schedule) {
this.schedule = schedule;
}
}
Schedule.java -
public class Schedule {
private String id;
#XmlAttribute(name = "ID")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
And then in java code-
JAXBContext context = JAXBContext.newInstance(SomeRoot.class);
Unmarshaller unMarshaller = context.createUnmarshaller();
File file = ResourceUtils.getFile("classpath:config/SomeRoot.xml");
SomeRoot param = (SomeRoot) unMarshaller.unmarshal(file);
List<Schedule> schedules = param.getSchedule();
for (Schedule schedule : schedules) {
LOGGER.info("Schedule: "+schedule.getId());
}

Related

How to pass #RequestBody list of object in XML

I have a rest application with PostMapping:
public List<Job> jobs = new ArrayList<Job>()
#PostMapping
public JobList handleXMLPostRequest (#Valid #RequestBody JobList newJobs)
{
for(Job joba : newJobs.getJobList())
jobs.add(joba);
for (Job joba : jobs)
System.out.println(joba.toString());
System.out.println("\n");
return newJobs;
}
Object Job:
#XmlRootElement(name = "job")
#XmlAccessorType(XmlAccessType.PROPERTY)
public class Job {
private int id;
private String type;
private String user;
private String device;
private int amount;
//getters and setters }
Object jobList:
#XmlRootElement(name = "jobs")
#XmlAccessorType(XmlAccessType.PROPERTY)
public class JobList {
public ArrayList<Job> jobList = new ArrayList<>();
//getter setter
}
Trying to post next XML:
<jobs>
<job>
<id>10</id>
<type>print</type>
<user>user1</user>
<device>device1</device>
<amount>10</amount>
</job>
<job>
<id>11</id>
<type>scan</type>
<user>user1</user>
<device>device1</device>
<amount>10</amount>
</job>
</jobs>
I need to read < jobs > as JobList, where each < job > will be Job object in this list.
When i run my example and pass it this xml list, it returns null list.
How to set this JobList right?
try with this,
JobsList.java
#XmlRootElement(name = "jobs")
#XmlAccessorType(XmlAccessType.PROPERTY)
public class JobList {
private ArrayList<Job> jobList;
#XmlElement(name="job")
public ArrayList<job> getJobList(){
return jobList;
}
public void setJobList(ArrayList<Job> jobList){
this.jobList = jobList;
}
}
Job.java
#XmlRootElement
#XmlAccessorType(XmlAccessType.PROPERTY)
public class Job {
private int id;
private String type;
private String user;
private String device;
private int amount;
#XmlElement
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
#XmlElement
public String getType(){
return type;
}
public void setType(String type){
this.type = type;
}
#XmlElement
public String getUser(){
return user;
}
public void setUser(String iser){
this.user = user;
}
#XmlElement
public String getDevice(){
return device;
}
public void setDevice(String device){
this.device = device;
}
#XmlElement
public int getAmount(){
return amount;
}
public void setAmount(int amount){
this.amount = amount;
}
}

Error reading XML via JaxB

This is my class structure:
#XmlRootElement(name="System")
public class SystemDTO () {
#XmlElement(name="ID")
public void setId(String id) {
this.id = id;
}
#XmlElement(name="Source")
public void setSource(SourceDTO source) {
this.source = source;
}
}
#XmlRootElement(name="Source")
class SourceDTO {
#XmlElement(name="Name")
public void setName(String name) {
this.name = name;
}
}
This is my XML File:
<System>
<ID>e5b160d0</ID>
<Source>
<Name>Kron</Name>
</Source>
</System>
The problem is the Source is always null. I do not get a exception, it just comes out null. I've attempted to use just the Source tag and it picks up Name just fine, but when I add it as part of the System class it does not seem to work.
Additionally I attempted to do this and have a string member variable in System for name:
#XmlElementWrapper(name="Source")
#XmlElement(name="Name")
But that causes an exception. Any ideas?
The Test Class
public class JaxbTest {
public static void main(String[] args) {
String xml = "<System>\n" +
" <ID>e5b160d0</ID>\n" +
" <Source>\n" +
" <Name>Kron</Name>\n" +
" </Source>\n" +
"</System>";
SystemDTO systemDTO;
try {
JAXBContext jaxbContext = JAXBContext.newInstance(SystemDTO.class);
StringReader reader = new StringReader(xml);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
systemDTO = (SystemDTO) jaxbUnmarshaller.unmarshal(reader);
System.out.println(systemDTO.getSource().getName());
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
Source DTO
#XmlRootElement(name = "Source")
class SourceDTO {
private String name = null;
public String getName() {
return name;
}
#XmlElement(name = "Name")
public void setName(String name) {
this.name = name;
}
}
System DTO
#XmlRootElement(name = "System")
public class SystemDTO {
private String id;
private SourceDTO source;
public String getId() {
return id;
}
public SourceDTO getSource() {
return source;
}
#XmlElement(name = "ID")
public void setId(String id) {
this.id = id;
}
#XmlElement(name = "Source")
public void setSource(SourceDTO source) {
this.source = source;
}
}
One possible problem that I see is that you have declared 2 "Root" elements in your XML. Try #XmlType on your Source class:
#XmlType(name="Source")
class SourceDTO {
...
}

Unmarshal XML with dynamic root element using JAXB

I'm trying to integrate with a third-party system and depending on the type of object, the root element of the returned XML document changes. For example:
GET /objecttype1-1/ returns:
<?xml version="1.0" encoding="UTF-8"?>
<objecttype1 xmlns="path">
<id>1</id>
<description>obj1</description>
</objecttype1>
and:
GET /objecttype2-3 returns:
<?xml version="1.0" encoding="UTF-8"?>
<objecttype2 xmlns="path">
<id>3</id>
<address>home</address>
</objecttype2>
Since the sub-elements are not guaranteed to be the same (other than id), I figured a List with #XmlMixed #XmlAnyElement will take care of them. But how do I map the root elements? #XmlRootElement(name="???")
Due to technology limitations, I'm not able to use EclipseLink/MOXy. Thanks.
Its been 5 years since this question was asked but I found working solution of the issue, sharing for the community.
First we define JAXB beans as follows:
#XmlRootElement(name = "objecttype1")
#XmlAccessorType(XmlAccessType.NONE)
public class Objecttype1 {
#XmlElement(name = "id")
private String id;
#XmlElement(name = "description")
private String description;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
#XmlRootElement(name = "objecttype2")
#XmlAccessorType(XmlAccessType.NONE)
public class Objecttype2 {
#XmlElement(name = "id")
private String id;
#XmlElement(name = "address")
private String address;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setDescription(String address) {
this.address = address;
}
}
Next we need the JAXB context and the unmarshaller itself:
private static final JAXBContext jaxbContext;
public Unmarshaller getUnmarshaller() {
try {
return jaxbContext.createUnmarshaller();
} catch (JAXBException ex) {
throw new IllegalStateException(ex);
}
}
Having that, the JAXB context is loading its candidates and checks if there is a match amongs them by the root element name. We just unmarshal and check whats the type of received object:
try {
Object unmarshalledObject = getUnmarshaller().unmarshal(new StringReader(xmlString));
if (unmarshalledObject instanceof Objecttype1) {
//do Objecttype1 related work
} else if (unmarshalledObject instanceof Objecttype2) {
//do Objecttype2 related work
} else {
// unexpected object type
}
} catch (JAXBException ex) {
//handle ex
}

File upload with #ManyToOne relationship in play framework

I have two entities: Student and Info and they linked by a #ManytoOne relationship. The entity Info is used to handle file upload and store upload file in database. I m able to save file path in database.but Not With Student_id. i want to save file with student id. and show the uploaded file with in table format.Any example suggestions are appreciated. I m new to web development.thanks Two Model entities linked by a #ManytoOne relationship. Model Info is as follows.
package models;
#Entity
public class Info extends Model {
public static Info findById(Long id) {
return find.byId(id);
}
#Id
public Long id;
public String picture;
#ManyToOne(cascade = CascadeType.PERSIST)
private Student student;
public static Model.Finder<Long, Info> find =
new Model.Finder<Long, Info>(Long.class, Info.class);
public Info(){
// Left empty
}
public Info(Student student ,Long id){
this.customer=customer;
this.id=id;
}
public String toString() {
return String.format("%s" ,id);
}
public void setPicture(String picture) {
this.picture = picture;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public String getPicture() {
return picture;
}
}
another student model
package models;
#Entity
public class Info extends Model{
private static List<Info> products;
#Id
public Long id;
public String name;
#OneToMany(mappedBy="student")
private List<Info> info;
public static Finder<Long, Student> find = new Finder<Long, Student>(Long.class, Student.class);
public Student() {
}
public Student(String btn){
this.btn = btn;
this.info = new ArrayList<Info>();
}
public String toString() {
return String.format("%s - %s" ,id, business_address);
}
public static Student findById(Long id) {
return find.where().eq("id", id).findUnique();
}
public List<Info> getInfo() {
return info;
}
public void setInfo(List<Info> info) {
this.info = info;
}
}
and InfoCon Controller is as follows
package controllers;
import java.io.File;
public class InfoCon extends Controller {
private static final Form<Info> infoForm = Form.form(Info.class);
public static Result save() {
Form<Info> boundForm = infoForm.bindFromRequest();
Info info = boundForm.get();
Http.MultipartFormData body = request().body().asMultipartFormData();
Http.MultipartFormData.FilePart picture = body.getFile("picture");
if (picture != null) {
String fileName = picture.getFilename();
String contentType = picture.getContentType();
File file = picture.getFile();
File newFile = new File("C:\\Folder1\\store\\"+ "_" + fileName);
file.renameTo(newFile); //here you are moving file to new directory
info.setPicture(newFile.getPath());
if (info.id == null) {
info.save();
}
return ok("File uploaded");
} else {
flash("error", "Missing file");
return redirect(routes.Application.index());
}
}
public static Result info(Long id) {
final Student student = Student.findById(id);
Info wk = new Info();
Form<Info> filledForm = infoForm.fill(wk);
return ok(info.render(filledForm));
}
}

Reading XML files from java

I am trying to read an XML file from java program. I am able to read its contents.I am posting the XML file from which i am reading contents.
<?xml version="1.0" encoding="UTF-8" ?>
<customer id="100">
<age>29</age>
<name>lucifer</name>
</customer>
i am able to write its contents through java program i am posting my code..
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Customer {
String name;
int age;
int id;
public String getName() {
return name;
}
#XmlElement
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
#XmlElement
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
#XmlAttribute
public void setId(int id) {
this.id = id;
}
}
public class CheckClass {
public static void main(String[] args) {
try {
File file = new File("./file/NewFile.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Customer customer = (Customer) jaxbUnmarshaller.unmarshal(file);
System.out.println(customer.age);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
But i have to read values from this XML file which i can not.This is my XML file
<?xml version="1.0" encoding="UTF-8"?>
<DBConfig ID="1" Name ="" DriverName="" HostName="localhost" PortName="" DBName="" ServiceName="" User="" PassWord="" sid="">
<TableConfig ID= "1" TableName="">
</TableConfig>
</DBConfig>
When i am trying to access this xml values through java class i am getting this error..
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
Class has two properties of the same name "DBName"
this problem is related to the following location:
at public java.lang.String com.gamma.DBConf.getDBName()
at com.gamma.DBConf
this problem is related to the following location:
at public java.lang.String com.gamma.DBConf.DBName
at com.gamma.DBConf
Class has two properties of the same name "sid"
this problem is related to the following location:
at public java.lang.String com.gamma.DBConf.getSid()
at com.gamma.DBConf
this problem is related to the following location:
at public java.lang.String com.gamma.DBConf.sid
at com.gamma.DBConf
at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(Unknown Source)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at javax.xml.bind.ContextFinder.newInstance(Unknown Source)
at javax.xml.bind.ContextFinder.newInstance(Unknown Source)
at javax.xml.bind.ContextFinder.find(Unknown Source)
at javax.xml.bind.JAXBContext.newInstance(Unknown Source)
at javax.xml.bind.JAXBContext.newInstance(Unknown Source)
at com.gamma.ReadXML.main(ReadXML.java:22)
and this is my java classes
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class DBConf {
public String Name;
public String DriverName;
public String HostName;
public String PortName;
public String DBName;
public String ServiceName;
public String User;
public String PassWord;
public String sid;
public String getName() {
return Name;
}
#XmlElement
public void setName(String name) {
Name = name;
}
public String getDriverName() {
return DriverName;
}
#XmlElement
public void setDriverName(String driverName) {
DriverName = driverName;
}
public String getHostName() {
return HostName;
}
#XmlElement
public void setHostName(String hostName) {
HostName = hostName;
}
public String getPortName() {
return PortName;
}
#XmlElement
public void setPortName(String portName) {
PortName = portName;
}
public String getDBName() {
return DBName;
}
#XmlElement
public void setDBName(String dBName) {
DBName = dBName;
}
public String getServiceName() {
return ServiceName;
}
#XmlElement
public void setServiceName(String serviceName) {
ServiceName = serviceName;
}
public String getUser() {
return User;
}
#XmlElement
public void setUser(String user) {
User = user;
}
public String getPassWord() {
return PassWord;
}
#XmlElement
public void setPassWord(String passWord) {
PassWord = passWord;
}
public String getSid() {
return sid;
}
#XmlElement
public void setSid(String sid) {
this.sid = sid;
}
}
And this is the main class
public class ReadXML {
/**
* #param args
*/
public static void main(String[] args) {
try {
File file = new File("./file/dbconfig.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(DBConf.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
DBConf db = (DBConf) jaxbUnmarshaller.unmarshal(file);
System.out.println(db.HostName);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
can anyone help
Note that you are annotating Attribute as Element. Fix that.
Even after that if problem occurs -
Try using - #XmlAccessorType(XmlAccessType.FIELD)
Move #XmlAttribute(name = "HostName") annotations to fields instead of accessor methods.
I am not sure if this is your problem. I faced a similar problem and this helped me. I wont guarantee that it will solve your problem but prima facie, it appears that above can fix it.
dbName, sid are Attributes, but you have annotated them #XmlElement. change all the attributes to #XmlAttribute.
Why don't you use
Xstream library
Example:
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
#XStreamAlias("Cat")
class Cat {
#XStreamAsAttribute
int age;
String name;
}
public class XStreamDemo {
public static void main(String[] args) {
XStream xstream = new XStream();
xstream.processAnnotations(Cat.class);
String xml = "<Cat age='4' ><name>Garfield</name></Cat>";
Cat cat = (Cat) xstream.fromXML(xml);
System.out.println("name -> " + cat.name);
System.out.println("age -> " + cat.age);
}
}
You need to add Xstream jar files in to classpath.
Use these classes.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"value"
})
#XmlRootElement(name = "TableConfig")
public class TableConfig {
#XmlValue
protected String value;
#XmlAttribute(name = "ID")
protected Byte id;
#XmlAttribute(name = "TableName")
protected String tableName;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Byte getID() {
return id;
}
public void setID(Byte value) {
this.id = value;
}
public String getTableName() {
return tableName;
}
public void setTableName(String value) {
this.tableName = value;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"tableConfig"
})
#XmlRootElement(name = "DBConfig")
public class DBConfig {
#XmlElement(name = "TableConfig", required = true)
protected TableConfig tableConfig;
#XmlAttribute(name = "ID")
protected Byte id;
#XmlAttribute(name = "Name")
protected String name;
#XmlAttribute(name = "DriverName")
protected String driverName;
#XmlAttribute(name = "HostName")
protected String hostName;
#XmlAttribute(name = "PortName")
protected String portName;
#XmlAttribute(name = "DBName")
protected String dbName;
#XmlAttribute(name = "ServiceName")
protected String serviceName;
#XmlAttribute(name = "User")
protected String user;
#XmlAttribute(name = "PassWord")
protected String passWord;
#XmlAttribute
protected String sid;
public TableConfig getTableConfig() {
return tableConfig;
}
public void setTableConfig(TableConfig value) {
this.tableConfig = value;
}
public Byte getID() {
return id;
}
public void setID(Byte value) {
this.id = value;
}
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
}
public String getDriverName() {
return driverName;
}
public void setDriverName(String value) {
this.driverName = value;
}
public String getHostName() {
return hostName;
}
public void setHostName(String value) {
this.hostName = value;
}
public String getPortName() {
return portName;
}
public void setPortName(String value) {
this.portName = value;
}
public String getDBName() {
return dbName;
}
public void setDBName(String value) {
this.dbName = value;
}
public String getServiceName() {
return serviceName;
}
public void setServiceName(String value) {
this.serviceName = value;
}
public String getUser() {
return user;
}
public void setUser(String value) {
this.user = value;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String value) {
this.passWord = value;
}
public String getSid() {
return sid;
}
public void setSid(String value) {
this.sid = value;
}
}

Categories