I am learning Spring MVC (with Thymeleaf) while porting over a JBoss Seam website to Spring MVC.
I am trying to replace a HTTPServlet (doPost to /myservlet) with a Spring Controller with the following code:
@RequestMapping(value="/myservlet", method = RequestMethod.POST)
public String executeAction(HttpServletRequest request, HttpServletResponse response) throws IOException {
StringBuilder buffer = new StringBuilder();
BufferedReader reader = request.getReader();
String line;
while((line = reader.readLine()) != null) {
buffer.append(line);
}
String payload = buffer.toString();
System.out.println("payload: " + payload);
return "/index";
}
This method needs to read the XML Payload (String) sent via a HTTP Post to this endpoint.
When the external client (.NET - which will be used in the live environment) invokes this I get the following log messages:
[org.springframework.web.servlet.PageNotFound] (default task-3) Request method 'POST' not supported
[org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver] (default task-3) Handler execution resulted in exception: Request method 'POST' not supported
I have also tried this as a HTTPServlet but with the same problem. Can someone please advise as to what I am doing wrong?
The web.xml contents are:
<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">
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
<!-- Send unauthorised request to the 404 page -->
<error-page>
<error-code>403</error-code>
<location>/404.html</location>
</error-page>
<!-- 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>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>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
</web-app>
The xml payload:
<Jobs>
<Job Action="Post">
<AdvertiserName>Advertiser1</AdvertiserName>
<AdvertiserType ValueID="15897">15897</AdvertiserType>
<SenderReference>01111111</SenderReference>
<DisplayReference>DISPLAYREF_635346301296069467_4445_Test89
</DisplayReference>
<Classification ValueID="6211">1002915</Classification>
<SubClassification></SubClassification>
<Position><![CDATA[CASE MANAGER]]></Position>
<Description><![CDATA[ The Case Manager role is the vital link between all parties within the mortgage application process. ...]]></Description>
<Country ValueID="246">United Kingdom</Country>
<Location ValueID="12096">Yorkshire</Location>
<Area ValueID="107646">Bradford</Area>
<PostalCode>BD1 1EE</PostalCode>
<ApplicationURL>http://removed.com/Application.aspx?uPjAaXJ9HmZ04+4i/bqmFAz
</ApplicationURL>
<Language ValueID="120036">2057</Language>
<ContactName>Joe Bloggs</ContactName>
<EmploymentType ValueID="2163">2163</EmploymentType>
<StartDate></StartDate>
<Duration></Duration>
<WorkHours ValueID="2190">2190</WorkHours>
<SalaryCurrency ValueID="1078">1007000</SalaryCurrency>
<SalaryMinimum>16200.00</SalaryMinimum>
<SalaryMaximum>16200.00</SalaryMaximum>
<SalaryPeriod ValueID="2178">1007600</SalaryPeriod>
<JobType>APPLICATION</JobType>
</Job>
</Jobs>
In case anyone else has this issue, the problem is related to the method signature and CSRF.
I got around this by following geoand's advice (thanks) by changing the method signature to add @RequestBody String payload
And by disabling CSRF for the specific URL (/myservlet) but leaving it enabled for the other URL's using the following in the spring security config:
<http auto-config="true" use-expressions="true" pattern="/myservlet" >
<csrf disabled="true"/>
</http>
<http auto-config="true" use-expressions="true" >
<access-denied-handler error-page="/403" />
<form-login login-page="/login.html" authentication-failure-url="/login-error.html" authentication-success-handler-ref="customAuthenticationSuccessHandler" />
<logout logout-success-url="/index" />
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/advertiser/**" access="hasRole('ROLE_ADVERTISER')" />
<csrf disabled="false"/>
</http>
Thank you all for your replies/comments.
Kaz