Reputation: 637
I was running a webapp application which publishes REST and SOAP services. Both of them were working fine when I run my app by gradle run (spring-boot plugin) or as an Java Application from STS. SOAP Services work perfectly when called from SoapUI or from $.soap ajax invocation from index.html whenever the application is run from gradle run or STS. I've just tried to deploy my webapp on Tomcat 7. Webapp static content and REST services are working fine. The problem is that SOAP services do not work.
I'm getting the following error code, either from index.html $.soap calls or from SoapUI tests:
POST http://localhost:8080/soap/ 405 (Method Not Allowed)
This is my servlet-context.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure
Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up
static resources in the ${webappRoot}/resources directory -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources
in the /WEB-INF/views directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<context:component-scan base-package="com.stw_2015.app" />
</beans>
And this the structure of my @Endpoint annotated class:
@Endpoint
public class SoapController {
private static final String NAMESPACE_URI = "http://com.stw_2015.app/soap";
private static final Logger logger = LoggerFactory.getLogger(SoapController.class);
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "registerActionRequest")
@ResponsePayload
public RegisterActionResponse registerAction (
@RequestPayload RegisterActionRequest registerActionRequest) {
................
}
}
Possibly, the reason is that POST requests to SOAP service are being rejected by Spring. Is there any way to enable them? All my REST services are GET requests, but I do know that @RequestMapping annotated methods can be annotated as GET or POST requests listeners. However, for my Soap service, I just don't know.
Can someone help me out? Thank you!
PD: Please tell me if I should paste some other file contents.
Upvotes: 1
Views: 5548
Reputation: 637
I managed to solve the problem. I was really missing the key point. All my Soap Services were using some MessageDispatcherServlet bean defined as this:
@EnableWs
@Configuration
public class SoapWebServicesConfig extends WsConfigurerAdapter {
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/soap/*");
}
// http://localhost:8080/soap/soap_description.wsdl -> Accesible
@Bean(name = "soap_description")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema actionsSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("SoapPort");
wsdl11Definition.setLocationUri("/soap");
wsdl11Definition.setTargetNamespace("http://com.stw_2015.app/soap");
wsdl11Definition.setSchema(actionsSchema);
return wsdl11Definition;
}
@Bean
public XsdSchema actionsSchema() {
return new SimpleXsdSchema(new ClassPathResource("soap_description.xsd"));
}
}
As I said, these services were working fine if run from STS or gradle run. The problem is this servlet was not defined on my web.xml file. Now that file look like this:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>spring-ws</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>/soap/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Before that, the appServlet servlet (which is configured with servlet-context.xml I previously showed) was trying to handle "/soap/*" requests. Now, spring-ws servlet is handling those requests, while appServlet is handling the rest of them.
Finally, I had to create a file like this, called spring-ws-servlet.xml and located at "WEB-INF" folder:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven />
<context:component-scan base-package="com.stw_2015.app" />
</beans>
Upvotes: 1