首页 > 解决方案 > 使用 Spring Boot 使用 SoapWeb 服务不起作用?

问题描述

我正在使用 open-jdk 11 和 spring boot 版本 2.3.0.RELEASE。我是肥皂网络服务的新手,我想尝试使用肥皂生产商样本进行测试。以下是我尝试使用的 wsdl 链接: http ://www.thomas-bayer.com/axis2/services/BLZService?wsdl

我在 pom.xml 中添加了以下插件,用于从 wsdl 生成类:

            <plugin>
                <groupId>org.jvnet.jaxb2.maven2</groupId>
                <artifactId>maven-jaxb2-plugin</artifactId>
                <version>0.14.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <generatePackage>soapws.credins.api</generatePackage>
                    <generateDirectory>${project.basedir}/src/main/java</generateDirectory>
                    <schemaDirectory>${project.basedir}/src/main/resources/wsdl</schemaDirectory>
                    <schemaIncludes>
                        <include>*.wsdl</include>
                    </schemaIncludes>
                    <clearOutputDir>true</clearOutputDir>
                </configuration>
            </plugin>

然后我运行 amvn install并且所有类都成功生成。我创建了一个Jaxb2Marshaller用于从 java 类转换为 xml 的 bean。下面是实现:

@Configuration
public class SoapConfiguration {

    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setPackagesToScan("package.api");
        return marshaller();
    }

}

之后,我创建了一个客户端类,它可以进行如下的肥皂调用:

@Component
public class BankClient {

    @Autowired
    private Jaxb2Marshaller marshaller;

    private WebServiceTemplate template;

    public DetailsType getBankDetails(String blz) {
        GetBankType request = new GetBankType();
        request.setBlz(blz);
        template = new WebServiceTemplate(marshaller);
        DetailsType detail = (DetailsType) template
                .marshalSendAndReceive("http://www.thomas-bayer.com/axis2/services/BLZService", request);
        return detail;
    }

}

执行调用时遇到问题:

org.springframework.oxm.MarshallingFailureException: JAXB marshalling exception; nested exception is javax.xml.bind.MarshalException
 - with linked exception:

我通过添加如下@XmlRootElementtoGetBankType类解决了这个问题:

    @XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "getBankType", propOrder = {
    "blz"
})
public class GetBankType {

    @XmlElement(required = true)
    protected String blz;

    /**
     * Gets the value of the blz property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getBlz() {
        return blz;
    }

    /**
     * Sets the value of the blz property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setBlz(String value) {
        this.blz = value;
    }

}

现在我被这个问题困住了:我无法弄清楚问题出在哪里。


org.springframework.ws.soap.client.SoapFaultClientException: The endpoint reference (EPR) for the Operation not found is http://www.thomas-bayer.com/axis2/services/BLZService and the WSA Action = 
    at org.springframework.ws.soap.client.core.SoapFaultMessageResolver.resolveFault(SoapFaultMessageResolver.java:38)
    at org.springframework.ws.client.core.WebServiceTemplate.handleFault(WebServiceTemplate.java:830)
    at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:624)
    at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)
    at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:390)
    at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:378)
    at soapws.client.BankUpClient.getBankDetails(BankUpClient.java:26)

我究竟做错了什么

标签: javaspring-bootweb-servicessoap

解决方案


首先@XmlRootElement从 package 中生成的类中删除package.api

接下来修改BankClient如下:

@Component
public class BankClient {

    @Autowired
    private Jaxb2Marshaller jaxb2Marshaller;

    private WebServiceTemplate template;

    public JAXBElement<GetBankResponseType> getBankDetails(String blz) {
        GetBankType getBankType = new GetBankType();
        getBankType.setBlz(blz);
        ObjectFactory objectFactory = new ObjectFactory();
        JAXBElement<GetBankType> request = objectFactory.createGetBank(getBankType);
        template = new WebServiceTemplate(jaxb2Marshaller);
        JAXBElement<GetBankResponseType> response = (JAXBElement<GetBankResponseType>) template
                .marshalSendAndReceive("http://www.thomas-bayer.com/axis2/services/BLZService", request);
        return response;
    }

}

要构建请求,您需要使用ObjectFactory从 WSDL 自动生成的类。 ObjectFactory类允许我们以编程方式从表示 XML 内容的 java 对象构造请求。

接下来要记住的是,您将从中获得的响应也WebServiceTemplateGetBankResponseType包装在 XML 内容的表示中。 GetBankResponseType将是一个对象,它将包含我们从肥皂接收到的信息的内容模型和属性值。

下面是 BankClient 的集成测试:

@ExtendWith(SpringExtension.class)
@SpringBootTest
public class BankClientTest {

    @Autowired
    private BankClient client;


    @BeforeEach
    public void setup() {
    }

    @Test
    void testGetBankDetails() {
        // setup
        String blzCode = "39580041";
        String bezeichnungExpected = "Dresdner Bank";
        String bicExpected = "DRESDEFF395";
        String ortExpected = "Düren, Rheinl";
        String plzExpected = "52304";
        // execute
        JAXBElement<GetBankResponseType> response = client.getBankDetails(blzCode);
        // verify
        assertEquals(bezeichnungExpected, response.getValue().getDetails().getBezeichnung());
        assertEquals(bicExpected, response.getValue().getDetails().getBic());
        assertEquals(ortExpected, response.getValue().getDetails().getOrt());
        assertEquals(plzExpected, response.getValue().getDetails().getPlz());
    }

}

推荐阅读