Unable to unmarshal an object inside another object - java

I have got an xml file:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns1:Data xmlns:ns1="http://vv.com/namespace">
<Addr>Address 1</Addr1>
<Locality>San Francisco</Locality>
<Country>Japan</Country>
<CountryCode>JP</CountryCode>
</ns1:Data>
</soapenv:Body>
</soapenv:Envelope>
AddressDto.java
#XmlRootElement(name = "Data", namespace = "http://vv.com/namespace")
public class AddressDto implements Serializable
{
private String street;
private String city;
private CountryDto country;
public AddressDto()
{
super();
}
#XmlElement(name = "Addr")
public String getStreet1()
{
return street;
}
public void setStreet1(final String street1)
{
this.street = street1;
}
#XmlElement(name = "Locality")
public String getCity()
{
return city;
}
public void setCity(final String city)
{
this.city = city;
}
public CountryDto getCountry()
{
return country;
}
public void setCountry(final CountryDto country)
{
this.country = country;
}
}
CountryDto file:
public class CountryDto implements Serializable
{
private String name;
private String code;
public CountryDto()
{
super();
}
#XmlElement(name = "CountryCode")
public String getCode()
{
return code;
}
public void setCode(final String code)
{
this.code = code;
}
#XmlElement(name = "Country")
public String getName()
{
return name;
}
public void setName(final String name)
{
this.name = name;
}
}
When i run the code
JAXBContext context = JAXBContext.newInstance(AddressDto.class);
Unmarshaller un = context.createUnmarshaller();
AddressDto emp = (AddressDto) un.unmarshal(response.getSOAPBody().extractContentAsDocument());
return emp;
I am able to get the street and city in AddressDto object. But the field country is displaying as null...Any idea whats going wrong here?
Thanks

Parser don't know what Country / CountryCode means. You defined only Addr and Locality as XmlElement inside your AddressDto class. Therefore you will get null.
You need to modify your xml to something like this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns1:Data xmlns:ns1="http://vv.com/namespace">
<Addr>Address 1</Addr1>
<Locality>San Francisco</Locality>
<CountryDto>
<Country>Japan</Country>
<CountryCode>JP</CountryCode>
</CountryDto>
</ns1:Data>
</soapenv:Body>
</soapenv:Envelope>
And also modify your addressDto so getCountry() is XmlElement as well:
#XmlElement(name = "CountryDto")
public CountryDto getCountry()
{
return country;
}
Now Country and CountryCode won't be null anymore

Related

What is the JAX-WS annotation to return an object

I want to expose a java class as a JAX-WS service. This works fine if I return a String from a method, but I can't figure out how to return an object. Looking at Oracle's example (https://docs.oracle.com/middleware/1212/wls/WSGET/jax-ws-examples.htm#WSGET117)
I thought this code should work:
#WebService
public class CCService implements CCServiceLocal {
/**
* Default constructor.
*/
public CCService() {
}
#WebMethod
#WebResult(name="ApplicationConstantReturnMessage")
public ApplicationConstant getConst( ) {
return new ApplicationConstant("Group", "SubGroup", "Id", "Code", "Text", "Description" );
}
}
But when I invoke it with SOAPUi, I get an empty response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getConstResponse xmlns="http://test.cc.com/" xmlns:ns2="http://example.org/complex">
<ns2:ApplicationConstantReturnMessage/>
</getConstResponse>
</soap:Body>
</soap:Envelope>
Can anyone tell me what I am missing?
Here is the ApplicationConstant class:
public class ApplicationConstant {
public ApplicationConstant(String group, String subGroup, String id, String code, String text, String desc ) {
this.group = group;
this.subGroup = subGroup;
this.id = id;
this.text = text;
this.code = code;
this.desc = desc;
}
public String group() { return group; }
public String subGroup() { return subGroup; }
public String constantIdentifier() { return id; }
public String constantText() { return text; }
public String constantCode() { return code; }
public String constantDesc() { return desc; }
private String group;
private String subGroup;
private String id;
private String text;
private String code;
private String desc;
}
OK, I found it. I needed some annotations in my ApplicationConstant class, along with a default no-arg constructor.
#XmlRootElement(name="ApplicationConstant")
public class ApplicationConstant {
public ApplicationConstant() {
}
public ApplicationConstant(String group, String subGroup, String id, String code, String text, String desc ) {
this.group = group;
this.subGroup = subGroup;
this.id = id;
this.text = text;
this.code = code;
this.desc = desc;
}
public String group() { return group; }
public String subGroup() { return subGroup; }
public String constantIdentifier() { return id; }
public String constantText() { return text; }
public String constantCode() { return code; }
public String constantDesc() { return desc; }
#XmlElement private String group;
#XmlElement private String subGroup;
#XmlElement private String id;
#XmlElement private String text;
#XmlElement private String code;
#XmlElement private String desc;
}

#RequestParam with pojo inside pojo

#RequestMapping(value = "/action")
public MyObject myAction(
#RequestParam(value = "prop1", required = false) String prop1,
#RequestParam(value = "prop2", required = false) String prop2,
#RequestParam(value = "prop3", required = false) String prop3) { ... }
And I have this instead many parameter and it's working:
public class MyObject {
private String prop1;
private String prop2;
private String prop3;
//Getters and setters
...
}
#RequestMapping(value = "/action")
public MyObject myAction(MyObject myObject)
But I have problem when I am trying avoid duplicate
public class MyClass {
private MyObject param;
//Getters and setters
...
}
#RequestMapping(value = "/action")
public MyObject myAction(MyClass myClass)
What should my url with parameters look like now?
param={prop1=a1&prop2=a2&prop3=a3&} ?
Actually requesting in same way works
#RestController
public class HelloController {
#RequestMapping(value = "/action")
public Person myAction(Person person) {
return person;
}
}
public class Person {
private String name;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
URL Request:
http://localhost:8080/action?name=George&address=UK
Response
{
"name":"George",
"address":"UK"
}

I can't read attributes with namespace (ns2) using JAXB to parse XML in Java

I have to read data from this XML file:
<SENT_112 xmlns:ns2="http://www.mf.gov.pl/SENT/2017/01/18/STypes.xsd" xmlns="http://www.mf.gov.pl/SENT/2017/01/18/SENT_112.xsd">
<Carrier><ns2:TraderInfo><ns2:IdSisc>PL957271726800000</ns2:IdSisc><ns2:TraderName>FIRMA SPÓŁKA Z OGRANICZONĄ ODPOWIEDZIALNOŚCIĄ</ns2:TraderName>
<ns2:TraderIdentityType>NIP</ns2:TraderIdentityType>
<ns2:TraderIdentityNumber>9572717268</ns2:TraderIdentityNumber>
</ns2:TraderInfo>
<ns2:TraderAddress><ns2:Street>Arysztacka</ns2:Street><ns2:HouseNumber>91A</ns2:HouseNumber><ns2:City>Cieszyn</ns2:City><ns2:Country>PL</ns2:Country><ns2:PostalCode>43-400</ns2:PostalCode></ns2:TraderAddress></Carrier>
</SENT_112>
My main class is using JAXB:
JAXBContext jc = JAXBContext.newInstance(SENT_112.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
SENT_112 sent_112 = (SENT_112) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(sent_112, System.out);
Carrier.java
public class Carrier implements java.io.Serializable {
private int nrCarrier;
//private String sentnumber;
private String IdSisc;
private String tradername;
private String traderidentitytype;
private String traderidentitynumber;
private String street;
private String housenumber;
private String city;
private String country;
private String postalcode;
//Contrutors
//Getters and Setters
//ToString Method
SENT_112.java
#XmlRootElement(name="SENT_112")
public class SENT_112 {
#XmlElement(name="Carrier")
private List<Carrier> carrier;
public List<Carrier> getCarrier() {
return carrier;
}
PACKAGE-INFO.JAVA
#XmlSchema(
namespace = "http://www.mf.gov.pl/SENT/2017/01/18/SENT_112.xsd",
elementFormDefault = XmlNsForm.QUALIFIED)
package com.przedlak.entity;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
And my Code return that
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SENT_112 xmlns="http://www.mf.gov.pl/SENT/2017/01/18/SENT_112.xsd">
<Carrier>
<nrCarrier>0</nrCarrier>
</Carrier>
</SENT_112>
What is wrong with my Code? I need read all information.
If you want to get all information, write your classes appropriately i.e. to retrieve all data. Change Carrier.java to :
Carrier.java
#XmlRootElement(name="Carrier")
#XmlAccessorType(XmlAccessType.FIELD)
public class Carrier implements java.io.Serializable
{
#XmlElement( name = "TraderInfo" )
private TraderInfo traderInfo;
#XmlElement( name = "TraderAddress" )
private TraderAddress traderAddress;
private int nrCarrier;
public int getNrCarrier() {
return nrCarrier;
}
public void setNrCarrier(int nrCarrier) {
this.nrCarrier = nrCarrier;
}
public TraderInfo getTraderInfo() {
return traderInfo;
}
public void setTraderInfo(TraderInfo traderInfo) {
this.traderInfo = traderInfo;
}
public TraderAddress getTraderAddress() {
return traderAddress;
}
public void setTraderAddress(TraderAddress traderAddress) {
this.traderAddress = traderAddress;
}
}
Then define two classes for TraderAddress, TraderInfo as:
TraderInfo
#XmlRootElement(name="TraderInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class TraderInfo
{
#XmlElement( name = "IdSisc")
private String IdSisc;
#XmlElement( name = "TraderName")
private String tradername;
#XmlElement( name = "TraderIdentityType")
private String traderidentitytype;
#XmlElement( name = "TraderIdentityNumber")
private String traderidentitynumber;
public String getIdSisc() {
return IdSisc;
}
public void setIdSisc(String idSisc) {
IdSisc = idSisc;
}
public String getTradername() {
return tradername;
}
public void setTradername(String tradername) {
this.tradername = tradername;
}
public String getTraderidentitytype() {
return traderidentitytype;
}
public void setTraderidentitytype(String traderidentitytype) {
this.traderidentitytype = traderidentitytype;
}
public String getTraderidentitynumber() {
return traderidentitynumber;
}
public void setTraderidentitynumber(String traderidentitynumber) {
this.traderidentitynumber = traderidentitynumber;
}
}
TraderAddress.java
#XmlRootElement(name="TraderInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class TraderAddress
{
#XmlElement( name = "Street")
private String street;
#XmlElement( name = "HouseNumber")
private String houseNumber;
#XmlElement( name = "City")
private String city;
#XmlElement( name = "Country")
private String country;
#XmlElement( name = "PostalCode")
private String postalCode;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getHouseNumber() {
return houseNumber;
}
public void setHouseNumber(String houseNumber) {
this.houseNumber = houseNumber;
}
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;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
}
With this setup, you should get full xml from marshalling:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SENT_112 xmlns="http://www.mf.gov.pl/SENT/2017/01/18/SENT_112.xsd">
<Carrier>
<TraderInfo>
<IdSisc>PL957271726800000</IdSisc>
<TraderName>FIRMA SPÓÅ?KA Z OGRANICZONÄ„ ODPOWIEDZIALNOÅšCIÄ„
</TraderName>
<TraderIdentityType>NIP</TraderIdentityType>
<TraderIdentityNumber>9572717268</TraderIdentityNumber>
</TraderInfo>
<TraderAddress>
<Street>Arysztacka</Street>
<HouseNumber>91A</HouseNumber>
<City>Cieszyn</City>
<Country>PL</Country>
<PostalCode>43-400</PostalCode>
</TraderAddress>
<nrCarrier>0</nrCarrier>
</Carrier>
</SENT_112>

JAXB - Adding same attributes to different elements

I carefully studied the discussion "JAXB Adding attributes..." and would like to move a little further.
For example, there is a following class:
#XmlRootElement(name = "company")
#XmlType(propOrder = {"id", "name", "address"})
public class Company {
private String id;
private String name;
private String address;
#XmlElement(name = "id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement(name = "address")
public String getAddress() {
return name;
}
public void setAddress(String address) {
this.address = address;
}
}
After marshaling an object we have:
<company>
<id>1</id>
<name>Abc</name>
<address>Mountain View, United States</address>
</company>
Is there an elegant solution, - for example using annotations #XmlPaths, #XmlPath, #XmlElements, #XmlElement, - to receive as a result:
<company>
<id>1</id>
<name lang="en">Abc</name>
<address lang="en">Mountain View, United States</address>
</company>
How about creating a custom String with the lang attribute and use that instead of string
for example :
public class LangString {
#XmlValue
protected String value;
#XmlAttribute(name = "lang")
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlSchemaType(name = "language")
protected String lang;
//GETTERS & SETTERS
}
Your code :
#XmlRootElement(name = "company")
#XmlType(propOrder = {"id", "name", "address"})
public class Company {
private String id;
private LangString name;
private LangString address;
#XmlElement(name = "id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement(name = "name")
public LangString getName() {
return name;
}
public void setName(LangString name) {
this.name = name;
}
#XmlElement(name = "address")
public LangString getAddress() {
return name;
}
public void setAddress(LangString address) {
this.address = address;
}
}
The code above was generated from an xsd schema for my application that had elements with the lang attribute thus the #XmlSchemaType.
Hope it helps

JAXB - change property name without changing variable name in class

So I have code like this:
#XmlRootElement(name = "person")
#XmlType(propOrder = {"name", "secondName"})
public class Person {
private String name;
private String secondName;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSecondName(String secondName) {
this.secondName = secondName;
}
public String getSecondName() {
return secondName;
}
}
And when I want to create XML file it makes me:
<person>
<name>John</name>
<secondName>Smith</secondName>
</person>
Is it any way to make in xml file <second-name> instead of <secondName> without changing in class on private String second-name?
Problem solved. I should just do this:
#XmlElement(name="second-name")
public String getSecondName() {
return secondName;
}

Categories

Resources