使用 Spring 启动时无法使用 SoapWeb 服务?
Consuming SoapWeb Services with Spring Boot not working?
我正在使用 open-jdk 11 和 spring 启动版本 2.3.0.RELEASE。我是肥皂网络服务的新手,我想尝试用肥皂生产商样本进行测试。下面是我尝试使用的 wsdl 的 link:
http://www.thomas-bayer.com/axis2/services/BLZService?wsdl
我在 pom.xml 中添加了以下插件,用于从 wsdl 生成 classes:
<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>
然后我运行一个mvn install
,所有的classes都生成成功了。我创建了一个 bean Jaxb2Marshaller
用于从 java class 转换为 xml。下面是实现:
@Configuration
public class SoapConfiguration {
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("package.api");
return marshaller();
}
}
之后,我创建了一个客户端 class,它进行如下 soap 调用:
@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:
我通过将 @XmlRootElement
添加到 GetBankType
class 解决了这个问题,如下所示:
@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)
我做错了什么
首先从包 package.api
.
中生成的 classes 中删除 @XmlRootElement
下一步修改 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;
}
}
要构建请求,您需要使用从 WSDL 自动生成的 class ObjectFactory
。
ObjectFactory
class 允许我们以编程方式构造来自 java 对象的请求,这些对象将表示 XML 内容。
接下来要记住的是,您将从 WebServiceTemplate
获得的响应也会 GetBankResponseType
包裹在 XML 内容的表示中。
GetBankResponseType
将成为一个对象,它将包含我们从 soap 接收到的信息的内容模型和属性值。
下面是 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());
}
}
我正在使用 open-jdk 11 和 spring 启动版本 2.3.0.RELEASE。我是肥皂网络服务的新手,我想尝试用肥皂生产商样本进行测试。下面是我尝试使用的 wsdl 的 link: http://www.thomas-bayer.com/axis2/services/BLZService?wsdl
我在 pom.xml 中添加了以下插件,用于从 wsdl 生成 classes:
<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>
然后我运行一个mvn install
,所有的classes都生成成功了。我创建了一个 bean Jaxb2Marshaller
用于从 java class 转换为 xml。下面是实现:
@Configuration
public class SoapConfiguration {
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("package.api");
return marshaller();
}
}
之后,我创建了一个客户端 class,它进行如下 soap 调用:
@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:
我通过将 @XmlRootElement
添加到 GetBankType
class 解决了这个问题,如下所示:
@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)
我做错了什么
首先从包 package.api
.
@XmlRootElement
下一步修改 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;
}
}
要构建请求,您需要使用从 WSDL 自动生成的 class ObjectFactory
。
ObjectFactory
class 允许我们以编程方式构造来自 java 对象的请求,这些对象将表示 XML 内容。
接下来要记住的是,您将从 WebServiceTemplate
获得的响应也会 GetBankResponseType
包裹在 XML 内容的表示中。
GetBankResponseType
将成为一个对象,它将包含我们从 soap 接收到的信息的内容模型和属性值。
下面是 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());
}
}