XML snippet:
<datasource formatted-name="blah" inline="blah">
<repository-location derived-from="blah" id="blah" path="blah" revision="blah" site="blah"/>
</datasource>
I am trying to unmarshal everything under one class (DataSource) with nested static classes. Here is my DataSource class:
#XmlRootElement(name = "datasource")
#XmlAccessorType(XmlAccessType.FIELD)
public class DataSource {
#XmlAttribute(name = "formatted-name")
protected String formattedName;
#XmlAttribute(name = "inline")
protected String inline;
#XmlElement(name = "repository-location")
protected RepositoryLocation repositoryLocation;
// public getters and setters for fields above
#XmlAccessorType(XmlAccessType.FIELD)
public static class RepositoryLocation {
#XmlAttribute(name = "derived-from")
protected String derivedFrom;
#XmlAttribute(name = "id")
protected String id;
#XmlAttribute(name = "path")
protected String path;
#XmlAttribute(name = "revision")
protected String revision;
#XmlAttribute(name = "site")
protected String site;
// public getters and setters for fields above
}
}
Unmarshaller:
JAXBContext jaxbContext = JAXBContext.newInstance(DataSource.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(responseXML);
dataSourceResponse = (DataSource) unmarshaller.unmarshal(reader);
I can successfully output DataSource fields "formattedName" and "inline", but "repositoryLocation" is null. Can someone help please?
JAXB is able to unmarshal without Getters/Setters and fields can even be private. Given the DataSource class above, having some generated toString method added to both DataSource and RepositoryLocation, the following prints out all properties:
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import java.io.StringReader;
public class Jaxb {
public static void main(String[] args) throws JAXBException {
String xml = "<datasource formatted-name=\"blah\" inline=\"blah\">\n" +
" <repository-location derived-from=\"blah\" id=\"blah\"" +
" path=\"blah\" revision=\"blah\" site=\"blah\"/>\n" +
"</datasource>";
JAXBContext context = JAXBContext.newInstance(DataSource.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
DataSource dataSource = (DataSource) unmarshaller.unmarshal(new StringReader(xml));
System.out.println(dataSource);
}
#XmlRootElement(name = "datasource")
#XmlAccessorType(XmlAccessType.FIELD)
private class DataSource {
#XmlAttribute(name = "formatted-name")
private String formattedName;
#XmlAttribute(name = "inline")
private String inline;
#XmlElement(name = "repository-location")
private RepositoryLocation repositoryLocation;
#XmlAccessorType(XmlAccessType.FIELD)
private class RepositoryLocation {
#XmlAttribute(name = "derived-from")
private String derivedFrom;
#XmlAttribute(name = "id")
private String id;
#XmlAttribute(name = "path")
private String path;
#XmlAttribute(name = "revision")
private String revision;
#XmlAttribute(name = "site")
private String site;
#Override
public String toString() {
return "RepositoryLocation{" +
"derivedFrom='" + derivedFrom + '\'' +
", id='" + id + '\'' +
", path='" + path + '\'' +
", revision='" + revision + '\'' +
", site='" + site + '\'' +
'}';
}
}
#Override
public String toString() {
return "DataSource{" +
"formattedName='" + formattedName + '\'' +
", inline='" + inline + '\'' +
", repositoryLocation=" + repositoryLocation +
'}';
}
}
}
Problem solved! I noticed my java 1.7 library is missing some jars. So I decided to go ahead upgrade to 1.8. It worked like magic!
Tried with java 1.7 too and it works and in xml.txt ,xml is saved
package testSingleJar.specificpackage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args ) throws Exception
{
JAXBContext jaxbContext = JAXBContext.newInstance(DataSource.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
String responseXML = "";
//filename is filepath string
BufferedReader br = new BufferedReader(new FileReader(new File("D:\\xml.txt")));
String line;
StringBuilder sb = new StringBuilder();
while((line=br.readLine())!= null){
sb.append(line.trim());
}
responseXML=sb.toString();
StringReader reader = new StringReader(responseXML);
DataSource dataSourceResponse = (DataSource) unmarshaller.unmarshal(reader);
System.out.println(dataSourceResponse.getRepositoryLocation().getDerivedFrom());
}
}
#XmlRootElement(name = "datasource")
#XmlAccessorType(XmlAccessType.FIELD)
class DataSource {
#XmlAttribute(name = "formatted-name")
protected String formattedName;
#XmlAttribute(name = "inline")
protected String inline;
#XmlElement(name = "repository-location")
protected RepositoryLocation repositoryLocation;
// public getters and setters for fields above
#XmlAccessorType(XmlAccessType.FIELD)
public static class RepositoryLocation {
#XmlAttribute(name = "derived-from")
protected String derivedFrom;
#XmlAttribute(name = "id")
protected String id;
#XmlAttribute(name = "path")
protected String path;
#XmlAttribute(name = "revision")
protected String revision;
#XmlAttribute(name = "site")
protected String site;
public String getDerivedFrom() {
return derivedFrom;
}
public void setDerivedFrom(String derivedFrom) {
this.derivedFrom = derivedFrom;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getRevision() {
return revision;
}
public void setRevision(String revision) {
this.revision = revision;
}
public String getSite() {
return site;
}
public void setSite(String site) {
this.site = site;
}
}
public String getFormattedName() {
return formattedName;
}
public void setFormattedName(String formattedName) {
this.formattedName = formattedName;
}
public String getInline() {
return inline;
}
public void setInline(String inline) {
this.inline = inline;
}
public RepositoryLocation getRepositoryLocation() {
return repositoryLocation;
}
public void setRepositoryLocation(RepositoryLocation repositoryLocation) {
this.repositoryLocation = repositoryLocation;
}
}
output : blah
Related
I have very interesting xml and i am try to convert this xml to pojo. after my jaxb unmarshalling its return empty object.
here is xml:
<ServiceResultOfArrayOfstringuHEDJ7Dj xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/HotelWeb.SanAdminSite.RestWebApi.App_Data">
<Data xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d2p1:string>1105</d2p1:string>
<d2p1:string>1111</d2p1:string>
</Data>
<Error>
<Code></Code>
<Message></Message>
</Error>
<InfoMessage></InfoMessage>
<IsSuccessful>true</IsSuccessful>
</ServiceResultOfArrayOfstringuHEDJ7Dj>
My POJO's :
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "ServiceResultOfArrayOfstringuHEDJ7Dj", namespace = "http://schemas.datacontract.org/2004/07/HotelWeb.SanAdminSite.RestWebApi.App_Data")
public class PostSendLogIdServiceXmlResult {
private String xmlns;
#XmlElement(name = "InfoMessage")
private String infoMessage;
#XmlElement(name = "Error")
private Error error;
#XmlElement(name = "Data")
private PostSendLogIdData data;
#XmlElement(name = "IsSuccessful")
private boolean isSuccessful;
public String getXmlns() {
return xmlns;
}
public void setXmlns(String xmlns) {
this.xmlns = xmlns;
}
public String getInfoMessage() {
return infoMessage;
}
public void setInfoMessage(String infoMessage) {
this.infoMessage = infoMessage;
}
public Error getError() {
return error;
}
public void setError(Error error) {
this.error = error;
}
public PostSendLogIdData getData() {
return data;
}
public void setData(PostSendLogIdData data) {
this.data = data;
}
public boolean isSuccessful() {
return isSuccessful;
}
public void setSuccessful(boolean successful) {
isSuccessful = successful;
}
#Override
public String toString() {
return "PostSendLogIdServiceXmlResult{" +
"xmlns='" + xmlns + '\'' +
", infoMessage='" + infoMessage + '\'' +
", error=" + error +
", data=" + data +
", isSuccessful=" + isSuccessful +
'}';
}
}
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "Error")
#XmlAccessorType(XmlAccessType.FIELD)
public class PostSendLogIdError {
#XmlElement(name = "Code")
private String code;
#XmlElement(name = "Message")
private String message;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.Arrays;
#XmlRootElement(name = "Data", namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")
#XmlAccessorType(XmlAccessType.FIELD)
public class PostSendLogIdData {
#XmlElement(name = "string")
private String[] postSendLogIds;
private String _xmlns;
public String[] getPostSendLogIds() {
return postSendLogIds;
}
public void setPostSendLogIds(String[] postSendLogIds) {
this.postSendLogIds = postSendLogIds;
}
public String get_xmlns() {
return _xmlns;
}
public void set_xmlns(String _xmlns) {
this._xmlns = _xmlns;
}
#Override
public String toString() {
return "PostSendLogIdData{" +
"postSendLogIds=" + Arrays.toString(postSendLogIds) +
", _xmlns='" + _xmlns + '\'' +
'}';
}
}
And My Jaxb converting implementation:
context = JAXBContext.newInstance(PostSendLogIdServiceXmlResult.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
PostSendLogIdServiceXmlResult unmarshal = (PostSendLogIdServiceXmlResult) unmarshaller.unmarshal(new StringReader(response));
After this I'm getting new PostSendLogIdServiceXmlResult object with empty values.
Can you give me any advice.
Thanks in Advance.
Look at the XML again. The namespace is not applied to the <Data> element, it is applied to the <string> sub-elements. Notice where the d2p1: prefix is applied.
Also, the <Data> is not a root element, so the entire #XmlRootElement(name = "Data", ... annotation is unused, i.e. unnecessary, and it seems to be confusing you, so I recommend removing the annotation from the PostSendLogIdData class.
Correct use is:
#XmlElement(name = "string", namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")
private String[] postSendLogIds;
I have the following files:
UnitController.java
package com.fidolease.fidolease.controllers;
import com.fidolease.fidolease.exceptions.ResourceNotFoundException;
import com.fidolease.fidolease.models.Unit;
import com.fidolease.fidolease.repository.UnitRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
#RequestMapping("/api/v1")
public class UnitController {
#Autowired
private UnitRepository unitRepository;
#GetMapping("/units")
public List<Unit> getAllUnits(){
return unitRepository.findAll();
}
#GetMapping("/units/{id}")
public ResponseEntity<Unit> getUnitById(#PathVariable(value = "id") Long unitId)
throws ResourceNotFoundException {
Unit unit = unitRepository.findById(unitId)
.orElseThrow(() -> new ResourceNotFoundException("Unit not found for this id :: " + unitId));
return ResponseEntity.ok().body(unit);
}
}
ErrorDetails.java
package com.fidolease.fidolease.exceptions;
import java.util.Date;
public class ErrorDetails {
private Date timestamp;
private String message;
private String details;
public ErrorDetails(Date timestamp, String message, String details) {
super();
this.timestamp = timestamp;
this.message = message;
this.details = details;
}
public Date getTimestamp() {
return timestamp;
}
public String getMessage() {
return message;
}
public String getDetails() {
return details;
}
}
GlobalExceptionHandler.java
package com.fidolease.fidolease.exceptions;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import java.util.Date;
#ControllerAdvice
public class GlobalExceptionHandler {
#ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<?> resourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}
#ExceptionHandler(Exception.class)
public ResponseEntity<?> globalExceptionHandler(Exception ex, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
ResourceNotFoundException.java
package com.fidolease.fidolease.exceptions;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends Exception{
private static final long serialVersionUID = 1L;
public ResourceNotFoundException(String message){
super(message);
}
}
Unit.java
package com.fidolease.fidolease.models;
import javax.persistence.*;
#Entity
#Table(name = "units")
public class Unit {
private long id;
private String unit_heading;
private int unit_type_id;
private int number_of_bedroom;
private double number_of_bathroom;
private int number_of_balcony;
private int leasing_info_id;
private String date_of_posting;
private String date_available_from;
private int posted_by;
private boolean is_active;
private String unit_description;
private int carpet_area;
private String unit_number;
private int unit_floor_number;
private int parent_unit_id;
public Unit(){ }
public Unit(String unit_heading, int unit_type_id, int number_of_bedroom, double number_of_bathroom,
int number_of_balcony, int leasing_info_id, String date_of_posting, String date_available_from,
int posted_by, boolean is_active, String unit_description, int carpet_area, String unit_number,
int unit_floor_number, int parent_unit_id) {
this.unit_heading = unit_heading;
this.unit_type_id = unit_type_id;
this.number_of_bedroom = number_of_bedroom;
this.number_of_bathroom = number_of_bathroom;
this.number_of_balcony = number_of_balcony;
this.leasing_info_id = leasing_info_id;
this.date_of_posting = date_of_posting;
this.date_available_from = date_available_from;
this.posted_by = posted_by;
this.is_active = is_active;
this.unit_description = unit_description;
this.carpet_area = carpet_area;
this.unit_number = unit_number;
this.unit_floor_number = unit_floor_number;
this.parent_unit_id = parent_unit_id;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId(){
return this.id;
}
public void setId(long id){
this.id = id;
}
#Column(name = "unit_heading", nullable = false)
public String getUnit_heading(){
return this.unit_heading;
}
public void setUnit_heading(String unit_heading){
this.unit_heading = unit_heading;
}
#Column(name = "unit_type_id", nullable = false)
public int getUnit_type_id(){
return this.unit_type_id;
}
public void setUnit_type_id(int unit_type_id){
this.unit_type_id = unit_type_id;
}
#Column(name = "number_of_bedroom", nullable = false)
public int getNumber_of_bedroom(){
return this.number_of_bedroom;
}
public void setNumber_of_bedroom(int number_of_bedroom){
this.number_of_bedroom = number_of_bedroom;
}
#Column(name = "number_of_bathroom", nullable = false)
public double getNumber_of_bathroom(){
return this.number_of_bathroom;
}
public void setNumber_of_bathroom(double number_of_bathroom){
this.number_of_bathroom = number_of_bathroom;
}
#Column(name = "number_of_balcony", nullable = false)
public int getNumber_of_balcony(){
return this.number_of_balcony;
}
public void setNumber_of_balcony(int number_of_balcony){
this.number_of_balcony = number_of_balcony;
}
#Column(name = "leasing_info_id", nullable = false)
public int getLeasing_info_id(){
return this.leasing_info_id;
}
public void setLeasing_info_id(int leasing_info_id){
this.leasing_info_id = leasing_info_id;
}
#Column(name = "date_of_posting", nullable = false)
public String getDate_of_posting(){
return this.date_of_posting;
}
public void setDate_of_posting(String date_of_posting){
this.date_of_posting = date_of_posting;
}
#Column(name = "date_available_from", nullable = false)
public String getDate_available_from(){
return this.date_available_from;
}
public void setDate_available_from(String date_available_from){
this.date_available_from = date_available_from;
}
#Column(name = "posted_by", nullable = false)
public int getPosted_by(){
return this.posted_by;
}
public void setPosted_by(int posted_by){
this.posted_by = posted_by;
}
#Column(name = "is_active", nullable = false)
public boolean getIs_active(){
return this.is_active;
}
public void setIs_active(boolean is_active){
this.is_active = is_active;
}
#Column(name = "unit_description", nullable = false)
public String getUnit_description(){
return this.unit_description;
}
public void setUnit_description(String unit_description){
this.unit_description = unit_description;
}
#Column(name = "carpet_area", nullable = false)
public int getCarpet_area(){
return this.carpet_area;
}
public void setCarpet_area(int carpet_area){
this.carpet_area = carpet_area;
}
#Column(name = "unit_number", nullable = false)
public String getUnit_number(){
return this.unit_number;
}
public void setUnit_number(){
this.unit_number = unit_number;
}
#Column(name = "unit_floor_number", nullable = false)
public int getUnit_floor_number(){
return this.unit_floor_number;
}
public void setUnit_floor_number(int unit_floor_number){
this.unit_floor_number = unit_floor_number;
}
#Column(name = "parent_unit_id", nullable = false)
public int getParent_unit_id(){
return this.parent_unit_id;
}
public void setParent_unit_id(int parent_unit_id){
this.parent_unit_id = parent_unit_id;
}
#Override
public String toString() {
return "Unit{" +
"id=" + id +
", unit_heading='" + unit_heading + '\'' +
", unit_type_id=" + unit_type_id +
", number_of_bedroom=" + number_of_bedroom +
", number_of_bathroom=" + number_of_bathroom +
", number_of_balcony=" + number_of_balcony +
", leasing_info_id=" + leasing_info_id +
", date_of_posting='" + date_of_posting + '\'' +
", date_available_from='" + date_available_from + '\'' +
", posted_by=" + posted_by +
", is_active=" + is_active +
", unit_description='" + unit_description + '\'' +
", carpet_area=" + carpet_area +
", unit_number='" + unit_number + '\'' +
", unit_floor_number=" + unit_floor_number +
", parent_unit_id=" + parent_unit_id +
'}';
}
}
UnitRepository.java
package com.fidolease.fidolease.repository;
import com.fidolease.fidolease.models.Unit;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface UnitRepository extends JpaRepository<Unit, Long> {
}
FidoLeaseApplication.java
package com.fidolease.fidolease;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class FidoleaseApplication {
public static void main(String[] args) {
SpringApplication.run(FidoleaseApplication.class, args);
}
}
When I run the application, I get the following error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'unitRepository' defined in com.fidolease.fidolease.repository.UnitRepository defined in #EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot resolve reference to bean 'jpaMappingContext' while setting bean property 'mappingContext'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
When I searched around, it seemed as if the error might occur if I don't have JPA in my pom file but after searching it, I have the following:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Does anyone have any suggestions as to what I am doing wrong here or maybe a reference to some documentation that may explain my issue? Thank you all for your time and if there is anything I can do to clarify, please let me know.
EDIT: The following is my properties file:
spring.datasource.initialization-mode=always
spring.datasource.platform=postgres
spring.datasource.url=jdbc:postgresql://digitaloceanservername:theport/mydbname
spring.datasource.username=myusername
spring.datasource.password=mypassword
Edit 2: Adding the full strack trac -> https://pastebin.com/RskBMJjL
There is a bug in your setter method for unit_number, it is not taking a parameter. It should be:
public void setUnit_number(String unit_number){
this.unit_number = unit_number;
}
I am trying to unmarshal XML to java class as follows:-
My xml file as follows:-
<Features_res>
<StartWeek>202017</StartWeek>
<EndWeek>202035</EndWeek>
<Pno12>ABCDEEB</Pno12>
<FeatureList>
<Feature>
<Code>T002</Code>
</Feature>
<Feature>
<Code>T002</Code>
</Feature>
</FeatureList>
</Features_res>
Java InteriorResponse:-
#XmlRootElement(name = "Features_res")
public class InteriorResponse {
#XmlElement(name = "StartWeek")
private int sWeek;
#XmlElement(name = "EndWeek")
private int eWeek;
#XmlElement(name = "Pno12")
private String p12;
List<Feature> featureList;
public InteriorResponse() {
}
public InteriorResponse(int startWeek, int endWeek, String pno12) {
super();
this.sWeek = startWeek;
this.eWeek = endWeek;
this.p12 = pno12;
}
public int getStartWeek() {
return sWeek;
}
public void setStartWeek(int startWeek) {
this.sWeek = startWeek;
}
public int getEndWeek() {
return eWeek;
}
public void setEndWeek(int endWeek) {
this.eWeek = endWeek;
}
public String getPno12() {
return p12;
}
public void setPno12(String pno12) {
this.p12 = pno12;
}
public List<Feature> getFeatureList() {
return featureList;
}
#XmlElement(name = "FeatureList")
public void setFeatureList(List<Feature> featureList) {
this.featureList = featureList;
}
}
Another Java Feature:-
#XmlRootElement(name = "Feature")
public class Feature {
//#XmlElement(name = "Feature")
private String feature_;
#XmlElement(name = "code")
private String code_;
public String getCode() {
return code_;
}
public void setCode(String code) {
this.code_ = code;
}
public String getFeature_() {
return feature_;
}
public void setFeature_(String feature_) {
this.feature_ = feature_;
}
}
I am using above class as :-
public static void xmlToInterior() {
File file = new File("minxml.xml");
JAXBContext jaxbContext;
try {
jaxbContext = JAXBContext.newInstance(InteriorResponse.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
InteriorResponse interiorFeatures = (InteriorResponse) unmarshaller.unmarshal(file);
List<Feature> list_feat = interiorFeatures.getFeatureList();
for(Feature ft : list_feat) {
System.out.println(ft.getCode());
}
} catch (JAXBException e) {
e.printStackTrace();
}
}
Output I have as:-
list_feat
code_ null
feature_ null
And list_feat has size 1. It should 2.
Also I have to name class member sWeek instead of startWeek. Otherwise, jaxbContext = JAXBContext.newInstance(InteriorResponse.class) throws exception like 2 element exist with same name.
XML additional part
I thought I could do the reaming part of the XML. I was trying part by part. But I couldn't do it. I really need to find some good tutorial or book about JXB. All I find a short overview of JXB. Any suggestion about where to read in details?
<Features_res>
<StartWeek>202017</StartWeek>
<EndWeek>202035</EndWeek>
<Pno12>ABCDEEB</Pno12>
<FeatureList>
<Feature>
<Code>T002</Code>
</Feature>
<Feature>
<Code>T002</Code>
</Feature>
</FeatureList>
<OptionList>
<Option>001048</Option>
<Option>000050</Option>
<Option>000790</Option>
</OptionList>
</Features_res>
So I made new class as:-
public class OptionList {
private List<Option> options;
#XmlElement(name = "Option")
public List<Option> getOptions() {
return options;
}
public void setOptions(List<Option> options) {
this.options = options;
}
}
Another class as :-
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
public class Option {
#XmlElement(name = "Option")
private String option_;
public String getOption() {
return option_;
}
public void setOption(String option) {
this.option_ = option;
}
}
And updated for InteriorResponse class as:-
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "Features_res")
public class InteriorResponse {
#XmlElement(name = "StartWeek")
private int sWeek;
#XmlElement(name = "EndWeek")
private int eWeek;
#XmlElement(name = "Pno12")
private String p12;
private FeatureList featureList;
private OptionList optionList;
public InteriorResponse() {}
public InteriorResponse(int startWeek, int endWeek, String pno12) {
super();
this.sWeek = startWeek;
this.eWeek = endWeek;
this.p12 = pno12;
}
public int getStartWeek() {
return sWeek;
}
public void setStartWeek(int startWeek) {
this.sWeek = startWeek;
}
public int getEndWeek() {
return eWeek;
}
public void setEndWeek(int endWeek) {
this.eWeek = endWeek;
}
public String getPno12() {
return p12;
}
public void setPno12(String pno12) {
this.p12 = pno12;
}
#XmlElement(name = "FeatureList")
public FeatureList getFeatureList() {
return featureList;
}
public void setFeatureList(FeatureList featureList) {
this.featureList = featureList;
}
#XmlElement(name = "OptionList")
public OptionList getOptionList() {
return optionList;
}
public void setOptionList(OptionList optionList) {
this.optionList = optionList;
}
#Override
public String toString() {
return "InteriorResponse{"
+ "sWeek="
+ sWeek
+ ", eWeek="
+ eWeek
+ ", p12='"
+ p12
+ '\''
+ ", featureList="
+ featureList
+ '}';
}
}
I couldn't get the Option.
option null
The total xml is really huge. I still would like to try the remaing parts by myself part by part.
You need to design your classes according to XML structure. Find below the classes.
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "Features_res")
public class InteriorResponse {
#XmlElement(name = "StartWeek")
private int sWeek;
#XmlElement(name = "EndWeek")
private int eWeek;
#XmlElement(name = "Pno12")
private String p12;
private FeatureList featureList;
private OptionList optionList;
public InteriorResponse() {}
public InteriorResponse(int startWeek, int endWeek, String pno12) {
super();
this.sWeek = startWeek;
this.eWeek = endWeek;
this.p12 = pno12;
}
public int getStartWeek() {
return sWeek;
}
public void setStartWeek(int startWeek) {
this.sWeek = startWeek;
}
public int getEndWeek() {
return eWeek;
}
public void setEndWeek(int endWeek) {
this.eWeek = endWeek;
}
public String getPno12() {
return p12;
}
public void setPno12(String pno12) {
this.p12 = pno12;
}
#XmlElement(name = "FeatureList")
public FeatureList getFeatureList() {
return featureList;
}
public void setFeatureList(FeatureList featureList) {
this.featureList = featureList;
}
#XmlElement(name = "OptionList")
public OptionList getOptionList() {
return optionList;
}
public void setOptionList(OptionList optionList) {
this.optionList = optionList;
}
#Override
public String toString() {
return "InteriorResponse{"
+ "sWeek="
+ sWeek
+ ", eWeek="
+ eWeek
+ ", p12='"
+ p12
+ '\''
+ ", featureList="
+ featureList
+ ", optionList="
+ optionList
+ '}';
}
}
Class for Feature object
import javax.xml.bind.annotation.XmlElement;
public class Feature {
#XmlElement(name = "Code")
private String code_;
public String getCode() {
return code_;
}
public void setCode(String code) {
this.code_ = code;
}
#Override
public String toString() {
return "Feature{" + "code_='" + code_ + '\'' + '}';
}
}
Class for FeatureList
import javax.xml.bind.annotation.XmlElement;
import java.util.List;
public class FeatureList {
private List<Feature> features;
#XmlElement(name = "Feature")
public List<Feature> getFeatures() {
return features;
}
public void setFeatures(List<Feature> features) {
this.features = features;
}
}
Class for OptionList
import javax.xml.bind.annotation.XmlElement;
import java.util.List;
public class OptionList {
private List<String> option;
#XmlElement(name = "Option")
public List<String> getOption() {
return option;
}
public void setOption(List<String> option) {
this.option = option;
}
}
For testing and simplicity, I have written a small java test program below.
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.util.List;
public class Test {
public static void main(String[] args) {
File file =
new File("E:\\so\\xml\\minxml.xml");
JAXBContext jaxbContext;
try {
jaxbContext = JAXBContext.newInstance(InteriorResponse.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
InteriorResponse interiorFeatures = (InteriorResponse) unmarshaller.unmarshal(file);
List<Feature> list_feat = interiorFeatures.getFeatureList().getFeatures();
List<String> optionList = interiorFeatures.getOptionList().getOption();
for (String option : optionList) {
System.out.println("Option Value : " + option);
}
for (Feature ft : list_feat) {
System.out.println(ft.getCode());
}
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
I also provide the sample xml structure below.
<Features_res>
<StartWeek>202017</StartWeek>
<EndWeek>202035</EndWeek>
<Pno12>ABCDEEB</Pno12>
<FeatureList>
<Feature>
<Code>T002</Code>
</Feature>
<Feature>
<Code>T002</Code>
</Feature>
</FeatureList>
<OptionList>
<Option>001048</Option>
<Option>000050</Option>
<Option>000790</Option>
</OptionList>
</Features_res>
I knew very little about JAXB stuff. I have learned a lot from Sambit who helped a lot and gave me the way to start with this JAXB. Later I have implemented my version with less number of Java class and more smart use of JAXB annotations.
My version of InteriorResponse class:-
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
#XmlRootElement(name = "Features_res")
public class InteriorResponse {
#XmlElement(name = "StartWeek")
private int startWeek;
#XmlElement(name = "EndWeek")
private int endWeek;
#XmlElement(name = "Pno12")
private String pno12;
#XmlElementWrapper(name = "FeatureList")
#XmlElement(name = "Feature")
private List<Feature> featureList;
#XmlElementWrapper(name = "OptionList")
#XmlElement(name = "Option")
private List<String> optionList;
public InteriorResponse() {
}
public InteriorResponse(int startWeek, int endWeek, String pno12) {
super();
this.startWeek = startWeek;
this.endWeek = endWeek;
this.pno12 = pno12;
}
#XmlTransient
public int getStartWeek() {
return startWeek;
}
public void setStartWeek(int startWeek) {
this.startWeek = startWeek;
}
#XmlTransient
public int getEndWeek() {
return endWeek;
}
public void setEndWeek(int endWeek) {
this.endWeek = endWeek;
}
#XmlTransient
public String getPno12() {
return pno12;
}
public void setPno12(String pno12) {
this.pno12 = pno12;
}
#XmlTransient
public List<Feature> getFeatureList() {
return featureList;
}
public void setFeatureList(List<Feature> featureList) {
this.featureList = featureList;
}
#XmlTransient
public List<String> getOptionList() {
return optionList;
}
public void setOptionList(List<String> optionList) {
this.optionList = optionList;
}
#Override
public String toString() {
return "InteriorResponse{" + "sWeek=" + startWeek + ", eWeek=" + endWeek + ", pno12='" + pno12 + '\'' + ", featureList=" + featureList + ", optionList="
+ optionList + '}';
}
}
My version of Feature class:-
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
public class Feature {
#XmlElement(name = "Code")
private String code;
#XmlTransient
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
#Override
public String toString() {
return "Feature{" + "code_='" + code + '\'' + '}';
}
}
Note that I don't need any extra wrapper class for FeatuerList and OptionList. It can be done by the JAXB annotation #XmlElementWrapper(name = "FeatureList"). Also, a very important lesson learned. We have to mark all the property's getter method as #XmlTransient. Otherwise, JAXB throws an exception 2 properties found with the same name. Because our class all properties is visible to the JAXB. So we have to mark one as #XmlTransient.
In my opion, it is a better solution than the accepted answer. I gave all the credit to Sambit. I hove this will help others.
I am using JAXB to covert xml to objects. After doing some tutorial, I can successfully convert a simple xml (which has single object and unique element tag) to object. Then I need to deal with more complicated xml which has multiple instances and one parent tag. I still use the similar structure. But I couldn't get the expected output of three country objects. what is wrong with my code? Please help.
IntelliJ IDE console output is:
Countries#5e20a82a
Process finished with exit code 0
xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Countries>
<Country>
<Country_Name>Spain</Country_Name>
<Country_Capital>Madrid</Country_Capital>
<Country_Continent>Europe</Country_Continent>
</Country>
<Country>
<Country_Name>USA</Country_Name>
<Country_Capital>Washington</Country_Capital>
<Country_Continent>America</Country_Continent>
</Country>
<Country>
<Country_Name>Japan</Country_Name>
<Country_Capital>Tokyo</Country_Capital>
<Country_Continent>Asia</Country_Continent>
</Country>
</Countries>
Countries.java
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlType( propOrder = { "name", "capital", "foundation", "continent" , "population"} )
#XmlRootElement( name = "Countries" )
public class Countries {
private int population;
private String name;
private String capital;
private int importance;
private String foundation;
private String continent;
#XmlElement(name = "Country_Population")
public void setPopulation(int population) {
this.population = population;
}
#XmlElement(name = "Country_Name")
public void setName(String name) {
this.name = name;
}
#XmlElement(name = "Country_Capital")
public void setCapital(String capital) {
this.capital = capital;
}
#XmlAttribute(name = "importance", required = true)
public void setImportance(int importance) {
this.importance = importance;
}
#XmlElement(name = "Country_foundation")
public void setFoundation(String foundation) {
this.foundation = foundation;
}
#XmlElement(name = "Country_Continent")
public void setContinent(String continent) {
this.continent = continent;
}
}
CountryReader.java
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
public class CountryReader {
public static void main(String[] args) throws JAXBException {
File file = new File("country.xml");
JAXBContext jaxbContext = JAXBContext.newInstance( Countries.class );
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Countries countres = (Countries)jaxbUnmarshaller.unmarshal( file );
System.out.println( countres );
}
}
You should separate the mapping of the root element and the nested collection elements.
So you'd have something like this:
#XmlRootElement( name = "Countries" )
public class Countries {
private List<Country> countries;
#XmlElement(name = "Country")
public void setCountries(List<Country> countries) {
this.countries = countries;
}
}
#XmlType( propOrder = { "name", "capital", "foundation", "continent" , "population"} )
#XmlRootElement( name = "Country" )
public class Country {
private int population;
private String name;
private String capital;
private int importance;
private String foundation;
private String continent;
#XmlElement(name = "Country_Population")
public void setPopulation(int population) {
this.population = population;
}
#XmlElement(name = "Country_Name")
public void setName(String name) {
this.name = name;
}
#XmlElement(name = "Country_Capital")
public void setCapital(String capital) {
this.capital = capital;
}
#XmlAttribute(name = "importance", required = true)
public void setImportance(int importance) {
this.importance = importance;
}
#XmlElement(name = "Country_foundation")
public void setFoundation(String foundation) {
this.foundation = foundation;
}
#XmlElement(name = "Country_Continent")
public void setContinent(String continent) {
this.continent = continent;
}
}
For more information about dealing with collections in JAXB, see this blog post. #XmlElementWrapper would seem suitable for your task, but I don't think it can be used directly with root elements.
This is my Parser class
public class Test {
public static void main(String args[]) throws Exception {
File file = new File("D:\\Test.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(MyOrder.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
MyOrder customer = (MyOrder) jaxbUnmarshaller.unmarshal(file);
System.out.println(customer.getOrder().getSide());
}
}
This is MyOrder.java file
#XmlRootElement(name = "BXML")
public class MyOrder {
#XmlElement(name = "Bag")
protected Order order;
public MyOrder() {
}
#XmlAttribute
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
This is my Domain Object (Order.java )
#XmlRootElement(name = "BXML")
public class Order {
public Order() {
}
#XmlAttribute(name = "Side")
protected BigInteger Side;
#XmlValue
public BigInteger getSide() {
return Side;
}
public void setSide(BigInteger side) {
Side = side;
}
}
This is the exception that I am getting when I tried to run the program
Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
#XmlAttribute/#XmlValue need to reference a Java type that maps to text in XML.
this problem is related to the following location:
at public com.Order com.MyOrder.getOrder()
at com.MyOrder
Class has two properties of the same name "order"
this problem is related to the following location:
at public com.Order com.MyOrder.getOrder()
at com.MyOrder
this problem is related to the following location:
at protected com.Order com.MyOrder.order
at com.MyOrder
For the #XmlAttribute/#XmlValue need to reference a Java type that maps to text in XML. issue you need to change your initialization of JAXBContext to the following:
JAXBContext jaxbContext = JAXBContext.newInstance(MyOrder.class, Order.class);
For the Class has two properties of the same name "order" issue, you need to change the definition of protected Order order; to private Order order;.
Also, you want to change the #XmlRootElement(name = "BXML") of your Order class to #XmlRootElement(name = "Order").
You can see the below sample code to generate Java Object from given XML.It is working fine in my system.
customer.xml
<?xml version="1.0" encoding="UTF-8"?>
<company>
<customer id="100">
<age>25</age>
<name>Ram</name>
<Address>
<city>Bangalore</city>
<country>India</country>
</Address>
<Address>
<city>Patna</city>
<country>India</country>
</Address>
</customer>
<customer id="200">
<age>26</age>
<name>Ashu</name>
<Address>
<city>Delhi</city>
<country>India</country>
</Address>
<Address>
<city>Madhubani</city>
<country>India</country>
</Address>
</customer>
</company>
Company.java
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name="company")
public class Company {
#XmlElement(name="customer")
private List<Costumer> custList;
//
public List<Costumer> getCustList() {
return custList;
}
public void setCustList(List<Costumer> custList) {
this.custList = custList;
}
//
#Override
public String toString() {
return "Company [custList=" + custList + "]";
}
}
Costumer.java
#XmlAccessorType(XmlAccessType.FIELD)
class Costumer {
#XmlElement(name="name")
private String name;
#XmlElement(name="age")
private int age;
#XmlElement(name="id")
private int id;
#XmlElement(name="Address")
private List<Address> addressList;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public List<Address> getAddressList() {
return addressList;
}
public void setAddressList(List<Address> addressList) {
this.addressList = addressList;
}
#Override
public String toString() {
return "Customer [name=" + name + ", age=" + age + ", id=" + id + ", addressList=" + addressList + "]";
}
}
Address.java
#XmlAccessorType(XmlAccessType.FIELD)
class Address {
#XmlElement(name="city")
private String city;
#XmlElement(name="country")
private String country;
//
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
//
#Override
public String toString() {
return "Address [city=" + city + ", country=" + country + "]";
}
}
TestMain.java
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class TestMain {
public static void main(String[] args) {
String xmlPath = "C:\\" + File.separator + "customer.xml";
try {
File file = new File(xmlPath);
JAXBContext jaxbContext = JAXBContext.newInstance(new Class[] {Company.class,Address.class,Costumer.class});
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Company customer = (Company) jaxbUnmarshaller.unmarshal(file);
System.out.println(customer);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
Outout:
Company [custList=[Customer [name=Ram, age=25, id=0, addressList=[Address [city=Bangalore, country=India], Address [city=Patna, country=India]]], Customer [name=Ashu, age=26, id=0, addressList=[Address [city=Delhi, country=India], Address [city=Madhubani, country=India]]]]]
This is because the sub-elements of that class you are creating JAXBcontext instance ,doesn't have the same name as of the element names defined inside it.
Example:
#XmlType(name = "xyz", propOrder = { "a", "b", "c", "d" })
#XmlRootElement(name = "testClass")
public class TestClass
{
#XmlElement(required = true)
protected Status status;
#XmlElement(required = true)
protected String mno;
#XmlElement(required = true)
}
In the above class you don't have "xyz" , but if you will put the property name that is not available JAXBContext instantiation throws IlligalAnnotationException.
If anyone is curious about the usage of JAXB and Lombok.
My fix was to remove the getter and setter from the root object.