我正在尝试挖掘Spring服务和JAXB类生成。在spring.io教程之后,我成功地创建了一个简单的web服务应用程序,但它并没有响应我的请求。下面是我的代码,配置(UPD修复了,多亏了DimasG,但仍然无法工作):
@EnableWs
@Configuration
public class WebServiceConfiguration extends WsConfigurerAdapter {
@Bean
public ServletRegistrationBean registrationBean(ApplicationContext context) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(context);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
@Bean(name = "employees")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema schema) {
DefaultWsdl11Definition definition = new DefaultWsdl11Definition();
definition.setPortTypeName("EmployeesPort");
definition.setLocationUri("/ws");
definition.setTargetNamespace("http://spring/demo/webservice");
definition.setSchema(schema);
return definition;
}
@Bean
public XsdSchema employeesSchema() {
return new SimpleXsdSchema(new ClassPathResource("xsd/employees.xsd"));
}
}
XSD模式文件:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://spring/demo/webservice"
targetNamespace="http://spring/demo/webservice" elementFormDefault="qualified">
<xs:element name="getEmployeeRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getEmployeeResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="employee" type="tns:employee"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="employee">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="age" type="xs:int"/>
<xs:element name="position" type="xs:string"/>
<xs:element name="gender" type="tns:gender"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="gender">
<xs:restriction base="xs:string">
<xs:enumeration value="M"/>
<xs:enumeration value="F"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
端点:
@Endpoint
public class EmployeeWebService {
private static final String NAMESPACE_URI = "http://spring/demo/webservice";
private final List<Employee> employees = new ArrayList<>();
@PostConstruct
public void init() {
employees.addAll(
Arrays.asList(
createEmployee("John Doe", 30, Gender.M, "Manager"),
createEmployee("Jane Doe", 27, Gender.F, "QA"),
createEmployee("Bob Johns", 28, Gender.M, "Programmer"),
createEmployee("Tiffany Collins", 24, Gender.F, "CEO"),
createEmployee("Alice", 25, Gender.F, "Secretary")
)
);
}
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getEmployeeRequest")
@ResponsePayload
public GetEmployeeResponse get(@RequestPayload GetEmployeeRequest request) {
Employee found = employees.stream()
.filter(emp -> emp.getName().equals(request.getName()))
.findFirst()
.orElseThrow(() -> new RuntimeException("Not found"));
GetEmployeeResponse response = new GetEmployeeResponse();
response.setEmployee(found);
return response;
}
}
SOAP getEmployeeRequest:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:gs="http://spring/demo/webservice">
<soapenv:Header/>
<soapenv:Body>
<gs:getEmployeeRequest>
<gs:name>Alice</gs:name>
</gs:getEmployeeRequest>
</soapenv:Body>
</soapenv:Envelope>
通过提供的代码,我将得到错误消息:
<faultstring xml:lang="en">No adapter for endpoint [public spring.demo.webservice.GetEmployeeResponse com.abondarenkodev.demo.spring.webservice.controller.EmployeeWebService.get(spring.demo.webservice.GetEmployeeRequest)]: Is your endpoint annotated with @Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?</faultstring>
我找到了一个可能的解决方案,可以用JAXBElement包装响应和请求类。端点方法如下所示:
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getEmployeeRequest")
@ResponsePayload
public JAXBElement<GetEmployeeResponse> get(@RequestPayload JAXBElement<GetEmployeeRequest> request) {
Employee found = employees.stream()
.filter(emp -> emp.getName().equals(request.getValue().getName()))
.findFirst()
.orElseThrow(() -> new RuntimeException("Not found"));
GetEmployeeResponse response = new GetEmployeeResponse();
response.setEmployee(found);
return new JAXBElement<>(
QName.valueOf("GetEmployeeResponse"),
GetEmployeeResponse.class,
response
);
}
JAXBElement有两个选项: jakarta.xml.bind.JAXBElement和javax.xml.bind.JAXBElement。对于jakarta,我得到了相同的'No adapter‘消息,而使用javax元素,我得到了"Not“异常,因为request.getValue()将以null的形式出现。
我发现的第二个可能的解决方案是检查请求和响应生成的类是否用XmlRootElement注释,并且它们确实被注释了。这是我的pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.abondarenkodev.demo.spring.webservice</groupId>
<artifactId>spring-soap-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-soap-demo</name>
<description>Demo project for Spring Boot WebServices</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.6.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<source>${project.basedir}/src/main/resources/xsd</source>
</sources>
<outputDirectory>${project.build.directory}/generated-sources/jaxb/</outputDirectory>
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>
</plugins>
</build>
</project>
我会感谢你的帮助。谢谢。
发布于 2022-06-26 20:30:16
我已经通过将Jaxb2 Maven插件降级到2.5.0版本来解决这个问题。这个插件的最后一个可用版本(3.1.0)使用jakarta生成类,而2.5.0使用javax导入生成类。
如果有人不小心踩到了这个问题,而你知道如何用雅加达进口来解决这个问题,请告诉我。
我的项目的最终pom文件如下(控制器中不需要JAXBElement ):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo.spring.webservice</groupId>
<artifactId>demo-spring-webservice</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-spring-webservice</name>
<description>Demo project for Spring Boot WebServices</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<source>${project.basedir}/src/main/resources/xsd</source>
</sources>
<outputDirectory>${project.build.directory}/generated-sources/jaxb/</outputDirectory>
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>
</plugins>
</build>
</project>
发布于 2022-06-24 10:51:36
在DefaultWsdl11Definition中,正如我所看到的,targetNameSpace与xsd中的不同。在ServletRegistrationBean /ws/*中应该是/webservice/*
https://stackoverflow.com/questions/72741201
复制相似问题