I have 10 fingers
I have 10 fingers

Reputation: 325

Spring RestTemplate deserialize xml to object return null

I have xml response and trying to deserialize it to pojo.

There are no exception and i can see the response is retrieved well but the result return null object.

I read bunch of similar article but none of them helped me.

<ArrayOfReserveInfo xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/">
  <ReserveInfo>
  <reserveId>8095727</reserveId>
  <bookingNo>00232003310080957272</bookingNo>
  <performanceId>124174</performanceId>
  <performance>performance</performance>
  <placeKr>CK</placeKr>
  <hallKr>hall</hallKr>
  <playYMD>20200331</playYMD>
  <startHM>1300</startHM>
  <dayName>2</dayName>
  <playNum>2</playNum>
  <scheCd>380926</scheCd>
  <reserveCnt>1</reserveCnt>
  <reserveUser>whoami</reserveUser>
  <pinCode>21</pinCode>
  <statusCd>02</statusCd>
  <statusNm>done</statusNm>
  <ticketAmt>1000</ticketAmt>
  <discountNm/>
  <printYN>N</printYN>
  <payAmt>1000</payAmt>
  <typeCd>99</typeCd>
  <typeName>normal</typeName>
  <reserveUserId>youcantseeme</reserveUserId>
  <reserveDate/>  
  </ReserveInfo>
</ArrayOfReserveInfo>

And this is my pojo

@Getter
@Setter
@XmlRootElement(name = "ArrayOfReserveInfo", namespace = "http://tempuri.org/")
@XmlAccessorType(XmlAccessType.FIELD)
public class UserReservationDto {
    @XmlElement(name = "ReserveInfo")
    private List<ReserveInfoDto> reserveInfoList;
}

@Getter
@Setter
@XmlRootElement(name = "ReserveInfo")
public class ReserveInfoDto {
    private String reserveId;
    private String bookingNo;
    private String performanceId;
    private String performance;
    private String placeKr;
    private String hallKr;
    private String playYMD;
    private String startHM;
    private String dayName;
    private String playNum;
    private String scheCd;
    private String reserveCnt;
    private String reserveUser;
    private String pinCode;
    private String statusCd;
    private String statusNm;
    private String ticketAmt;
    private String discountNm;
    private String printYN;
    private String payAmt;
    private String typeCd;
    private String typeName;
    private String reserveUserId;
    private String reserveDate;    
}

finally my client code

String url = HOST.concat("GetReserveList");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("companyCd", "SP0023");
params.add("pinCode", pinCode);
params.add("bookingNo", "");
params.add("userName", userName);
params.add("statusCd", "");

HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
UserReservationDto result = restTemplate.postForObject(url, entity, UserReservationDto.class);

If you guys need more info please let me know!

My environment

Upvotes: 1

Views: 6333

Answers (2)

Beezer
Beezer

Reputation: 1108

Just in case anyone wanted an XML to String deserialization example of a GET with an input parameter, here is a Kotlin example (easily convertible to Java in Intellij); my need was a quick and dirty so I could check the response payload. I had to do a lot of looking around for the following (what you see is what you get) and this code should run out the box, with the following:

id("org.springframework.boot") version "2.7.3"
testImplementation("org.springframework.boot:spring-boot-starter-test") 
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Test

@ActiveProfiles("test")
@SpringBootTest(classes = [YourMainSpringBootApplication::class],
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class TestControllerIT {

    @LocalServerPort
    private val port = 0

    @Autowired
    private val restTemplate: TestRestTemplate? = null

    @Test
    fun givenCUT_whenAutowired_thenSuccessful() {
        assertNotNull(restTemplate)
    }

    @Test
    fun givenCUT_whenFetchingAllBillingTypes_thenWeSucceed() {
        val restTemplate = RestTemplate()
        val uri = "http://localhost:$port/api/test/billing/xml/month/{month}/"
        val params: MutableMap<String, String> = HashMap()
        params["month"] = "2022-09-01"
        val stringResponse = restTemplate.getForObject(uri, String::class.java, params)
        assertNotNull(stringResponse)
        assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
                "<bi:blahblah xmlns:bi=\"urn:blahblahblahblah\"/>\n", stringResponse)
    }

Upvotes: 1

Marcos Barbero
Marcos Barbero

Reputation: 1119

To make it work, I did this:

Added this dependency:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

Then I changed your UserReservationDto class to this:

@Getter
@Setter
@XmlRootElement(name = "ArrayOfReserveInfo", namespace = "http://tempuri.org/")
@XmlAccessorType(XmlAccessType.FIELD)
@ToString
static class UserReservationDto {
    @JacksonXmlElementWrapper(useWrapping = false)
    @JacksonXmlProperty(localName = "ReserveInfo")
    private List<ReserveInfoDto> reserveInfo;
}

And I added the Accept header to XML, like this:

HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_XML));

I pushed a working copy of it at this repo.

Upvotes: 7

Related Questions