尝试使用 WebClient 从 Spring Boot 调用带有 XML 响应的 API 时出现 UnmarshalException

问题描述 投票:0回答:1

我正在尝试在 Spring Boot 应用程序中使用 WebClient 调用返回 XML 响应的 API。我确信我收到了 API 调用的 200,但代码无法将响应解析为 Java POJO(定义)。我收到如下错误

threw exception [Request processing failed: org.springframework.core.codec.DecodingException: Could not unmarshal XML to class com.intel.eae.expenseautomationengine.concur.models.Definitions] with root cause

jakarta.xml.bind.UnmarshalException: unexpected element (uri:"http://www.concursolutions.com/api/expense/extract/2010/02", local:"definitions"). Expected elements are <{}definition>,<{}definitions>

下面是我的代码片段

使用WebClient调用API

String definitionURL = "/api/expense/extract/v1.0";
    Definitions definitions = webClient
            .get()
            .uri(definitionURL)
            .accept(MediaType.APPLICATION_XML)
            .headers(httpHeaders -> httpHeaders.setBearerAuth("<<AUTH>>"))
            .retrieve()
            .bodyToMono(Definitions.class)
            .block();
    log.info("Response is {}", definitions);

WebClient Bean 配置

@Bean
public WebClient webClient() {
    return WebClient.builder()
            .exchangeStrategies(
                    ExchangeStrategies.builder()
                            .codecs(clientCodecConfigurer -> clientCodecConfigurer.defaultCodecs().jaxb2Decoder(new Jaxb2XmlDecoder()))
                            .build())
            .baseUrl(concurApiURL)
            .build();
}

我的响应模型(Definitions.java)

import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@XmlRootElement(name = "definitions")
@XmlAccessorType(XmlAccessType.FIELD)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Definitions {
    public List<Definition> definition;
    public String xmlns;
    public String i;
}

定义.java

import jakarta.xml.bind.annotation.XmlRootElement;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@XmlRootElement(name = "definition")
public class Definition {
    private String id;
    private String name;
    private String joblink;
}

最后是来自 API 的响应 XML

<definitions xmlns="http://www.concursolutions.com/api/expense/extract/2010/02" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <definition>
        <id>https://us2.concursolutions.com/api/expense/extract/v1.0/gWur87rvH6sJ7PAGiQwjZXFeYCXObXKvVow</id>
        <name>ADV AP/GL Extract V.2.4.3</name>
        <job-link>https://us2.concursolutions.com/api/expense/extract/v1.0/gWur87rvH6sJ7PAGiQwjZXFeYCXObXKvVow/job</job-link>
    </definition>
</definitions>

当我删除线时

@XmlAccessorType(XmlAccessType.FIELD)

从我的定义模型中,我得到了如下不同的错误


org.glassfish.jaxb.runtime.v2.runtime.IllegalAnnotationsException: 3 counts of IllegalAnnotationExceptions

我花了几个小时试图弄清楚这里出了什么问题。任何帮助将不胜感激

spring-boot xml-parsing unmarshalling spring-webclient
1个回答
0
投票

我能够通过在我的 java 包文件夹中使用 @XmlSchema 注释添加带有命名空间定义的 package-info.java 来添加上述工作,从而实现上述工作。

类似下面的内容

@XmlSchema(
    namespace = "http://www.concursolutions.com/api/expense/extract/2010/02",
    elementFormDefault = XmlNsForm.QUALIFIED
)
package com.concur.models.xml;
© www.soinside.com 2019 - 2024. All rights reserved.