Not able to send JSON request to spring controller from Ajax - java

I'm using Spring MVC to create my project template.
I'm trying to send a JSON request to my spring controller using Ajax, I tried by adding the content type of json etc. Its a POST request. however the trials got failed.
index.jsp
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$.ajax({
url:"getNames",
type:"POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({"name":"testName"}),
async: false,
cache: false,
dataType : "json",
processData:false,
success: function(resposeJsonObject){
// Success Action
}
});
});
</script>
Controller
My total controller other than imports
#Controller
public class HelloWorldController {
// Produces JSON data
#RequestMapping(value="hello",produces="application/json")
public #ResponseBody String helloWorld() throws JSONException {
JSONObject obj = new JSONObject();
obj.put("my key", "my Value");
return obj.toString();
}
// Accept JSON data
#RequestMapping(value="getNames", method=RequestMethod.POST)
public #ResponseBody Test addNewWorker(#RequestBody Test jsonString) {
Test test = new Test();
test.setName(jsonString.getName());
System.out.println(test.getName());
return test;
}
Web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>Spring3MVC</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
My Test class
public class Test implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
My configuration file of spring
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="net.viralpatel.spring3.controller" />
<bean id="test" class="com.qiib.spring3.model.Test"></bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
Error
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver logException
WARNING: Handler execution resulted in exception: Content type 'application/json;charset=UTF-8' not supported
Following JAR's are available in my project
aopalliance-1.0.jar
commons-logging-1.2.jar
jackson-core-asl-1.9.13.jar
jackson-databind-2.1.4.jar
jackson-mapper-asl-1.9.13.jar
jackson-servlet-api-3.1.0.jar
jstl-1.2.jar
spring-aop-4.2.0.RELEASE.jar
spring-beans- ""
spring-context-""
spring-core-""
spring-expression-""
spring-web-""
spring-webmvc-4.2.0.RELEASE.jar

I've imported your code into mine project and it works absolutely fine. You should check your beans and pom.xml. I'm posting my code and result:
Controller:
#RequestMapping(value="getNames", method=RequestMethod.POST)
public #ResponseBody Test addNewWorker(#RequestBody Test jsonString) {
Test test = new Test();
test.setName(jsonString.getName());
System.out.println(test.getName());
return test;
}
index.js:
$.ajax({
url:"getNames",
type:"POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({"name":"testName"}),
async: false,
cache: false,
dataType : "json",
processData:false,
success: function(resposeJsonObject){
// Success Action
}
});
output:
2017-08-17 08:59:22.045 INFO 7092 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2017-08-17 08:59:22.046 INFO 7092 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2017-08-17 08:59:22.049 INFO 7092 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 3 ms
testName

Related

#RequestBody with jQuery to map json Data to RequestBody. shows media type exception in browser [duplicate]

This question already has answers here:
Spring MVC 415 Unsupported Media Type
(8 answers)
Closed 5 years ago.
I am new to spring,I have tried with different ways to get the solution,
I have to use #RequestBody to get the json data which coming from jQuery.
I read the spring doc but i didn't find any thing clear.reg what jar need to add and how to map in xml file.
I tried
headers={"Accept=application/json"}
produces="application/json", consumes = "application/json"
consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE
application/x-www-form-urlencoded
MappingJacksonHttpMessageConverter(but i didn't want to used because i think its springBoot class)
#RequestMapping(method = RequestMethod.PUT) headers = "Accept=application/json"
UserController.java
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.evon.model.user.UserModel;
#Controller
public class UserController {
#RequestMapping(value = "/register",method = RequestMethod.POST)
public void handleXMLPostRequest (#RequestBody UserModel user) {
System.out.println(user);
System.out.println(user.getUserId());
System.out.println(user.getEmailId());
System.out.println(user.getPassword());
}
}
UserModel.java
public class UserModel implements Serializable
{
private Integer userId;
private String emailId;
private String password;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>withDiffServletName</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>demo</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>demo</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/demo-servlet.xml</param-value>
</context-param>
<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener </listener-class>
</listener>
</web-app>
demo-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:context = "http://www.springframework.org/schema/context"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package = "com.evon.model.controller,com.evon.model.user" />
<context:annotation-config/>
<mvc:annotation-driven />
</beans>
index.jsp
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript">
//Ajax submit create user
function ajaxSubmitCreateUserForm() {
alert("==ajaxSubmitCreateUserForm");
try{
$.ajax({
beforeSend: function(xhrObj){
xhrObj.setRequestHeader("Content-Type","application/json");
xhrObj.setRequestHeader("Accept","application/json");
},
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
type: "POST",
url : 'register',
data: JSON.stringify({
userId : "101",
password : "password",
emailId : "ankit.bhimjiyani#gmail.com"
}),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function(json){
console.log(json);
},
error : function() {
alert('System error occured, please try again ...');
}
});
}catch (e) {
alert(e)
}}
</script>
<div class="buttonBlock">
<button class="submitBTN" onclick="ajaxSubmitCreateUserForm();">Submit</button>
</div>
directory Structure
Can you try adding a return type for your controller and annotate your method as #ResponseBody. I think the issue is kainly because jquery is expecting a response back from the server and you are not sending it. Can you please try that.
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.5'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.7.5'
compile 'com.fasterxml.jackson.core:jackson-core:2.7.5' include this jars in classpath
you have to use produces and consumes into RequestMapping. you can refer bellow code:
#RestController
#RequestMapping("/city")
public class CityController {
private static final Logger logger = LoggerFactory.getLogger(CityController.class);
#Autowired(required = true)
private CityService cityService;
#RequestMapping(method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
public RestResponse save(#RequestBody CityView cityView) {
}

Getting 415 error while trying to call rest post method using spring

I am trying to implement spring rest method with post type. I am trying to retrieve JSON and convert it into java object. And returning with JSON only. Here is my code
package com.restService
#RestController
#RequestMapping(value="/user")
public class UserRestController {
#RequestMapping(value = "/post/create", method = RequestMethod.POST,consumes=MediaType.APPLICATION_JSON)
public #ResponseBody ResponseEntity<String> authenticateMobUser(#RequestBody User objUser) {
String result = null;
result = createUser(objeUser);
return new ResponseEntity<String>(result, HttpStatus.OK);
}
private String createUser(User objUser) {
// My create user code here
return "{\"status\":\"SUCCESS\",\"message\":\"SUCCESS\"}";
}
}
public class User {
String id;
String name;
// Getter and setters are present
}
Here is Spring configurations
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<tx:annotation-driven/>
<context:component-scan base-package="com.restService" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
</bean>
<!-- Configure to plugin JSON as request and response in method handler -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonMessageConverter"/>
</list>
</property>
</bean>
<!-- Configure bean to convert JSON to POJO and vice versa -->
<bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</bean>
</beans>
Here is my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>UserManagement</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springServlet-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Finally here is rest client I am using to call service
Client client = Client.create();
String strURL = null;
String domainName = "http://localhost:8080";
strURL = domainName + "/UserManagement/user/post/create";
String input = "{\"id\":\"12345\",\"name\":\"navnath\"}";
WebResource webResource = client.resource(strURL);
ClientResponse response = webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(ClientResponse.class, input);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatus());
}
When I run this code, I received "415 unsupported media type". while sending and retrieving, I am using MediaType.APPLICATION_JSON still getting this error.
Surly I am doing something wrong here but what it is, not getting
Don't you have to use MediaType.APPLICATION_JSON_VALUE in your RequestMapping?
Also, try to use RestTemplate instead of client if it is possible.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
String input = "{\"id\":\"12345\",\"name\":\"navnath\"}";
HttpEntity<String> entity = new HttpEntity<>(input, headers);
ResponseEntity<String> responseEntity = restTemplate.postForEntity("/user/post/create", entity, String.class);
if (responseEntity.getStatusCode().value() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ responseEntity.getStatusCode().getReasonPhrase());
}
P.S. To solve the issue replace your AnnotationMethodHandlerAdapter in spring config with .

Spring MVC request with null response in Json to Java object conversion

My ajax request in spring mvc
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/json2/20150503/json2.js"></script>
<script>
$(document).ready(function(){
var producer = "producer";
var model = "model";
var price = "1";
var ResponseModel = {};
ResponseModel.producer=producer;
ResponseModel.model=model;
ResponseModel.price=price;
$.ajax({
url : '/ajaxtest',
data: JSON.stringify({"editUserRequest":ResponseModel}),
type: "POST",
async: true,
beforeSend: function(xhr) {
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
},
success : function(data) {
alert("success");
console.log(data);
},
error:function(data) {
alert("errorxxx");
console.log(data);
}
});
});
</script>
Model
#JsonSerialize
public class ResponseModel implements Serializable {
public ResponseModel(){}
public String getProducer() {
return producer;
}
public void setProducer(String producer) {
this.producer = producer;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
private String producer;
private String model;
private String price;
}
and spring MVC controller
#Controller
#RequestMapping("/")
public class HelloController {
#RequestMapping(method = RequestMethod.GET)
public String printWelcome(ModelMap model) {
model.addAttribute("message", "Hello world!");
return "hello";
}
//#ModelAttribute(value="editUserRequest")
#RequestMapping(value = "/ajaxtest", method = RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody
String getTime(#ModelAttribute(value="editUserRequest") ResponseModel editUserRequest,HttpServletRequest request,HttpServletResponse response) {
String result = editUserRequest.getModel()+editUserRequest.getPrice()+editUserRequest.getProducer();
//String result = "editUserRequest";
//System.out.println("Debug Message from CrunchifySpringAjaxJQuery Controller.." + new Date().toString());
return result;
}
}
web.xml is
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring MVC Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
and dispatcher servlets is
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.springapp.mvc"/>
<context:annotation-config />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
after sending ajax request in firebug it shows null result by post is done successfully by lands in ajax error .
I have pom.xml with <jackson.version>2.6.3</jackson.version>
<!-- Need this for json to/from object -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
But can not use it map in Spring MVC 4 json to java object. How to solve it??
Ok I have replicated your issue in my machine. To send the data from ajax call to spring mvc in the form of an object, you need to make few changes to the ajax call and you need to change the #ModelAttribute to #RequestBody. See below the updated code
$(document).ready(function(){
var producer = "producer";
var model = "model";
var price = "1";
var editUserRequest = new Object();
editUserRequest.producer=producer;
editUserRequest.model=model;
editUserRequest.price=price;
$.ajax({
url : 'ajaxtest',
data: JSON.stringify(editUserRequest),
type: "POST",
contentType : 'application/json; charset=utf-8',
dataType : 'json',
success : function(data) {
alert("success");
console.log(data);
},
error:function(data) {
alert("errorxxx");
console.log(data);
}
});
});
The Spring Controller method
#RequestMapping(value = "ajaxtest", method = RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody
ResponseModel getTime(#RequestBody ResponseModel editUserRequest) {
String result = editUserRequest.getModel()+editUserRequest.getPrice()+editUserRequest.getProducer();
//String result = "editUserRequest";
//System.out.println("Debug Message from CrunchifySpringAjaxJQuery Controller.." + new Date().toString());
return editUserRequest;
}
Since in the ajax call you are expecting a JSON response and you are returning a plain String from spring controller. It goes to error handler in ajax call. I have changed the response type of spring controller method to ResponseModel so that the response will be in JSON format and in the ajax call the control goes to success handler.

Spring integration http testing

I am trying to test the routing I have configured on my http inbound channel. The test is working if I have the following test code:
#Test
public void success() throws JsonProcessingException, ServletException, IOException, Exception {
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(createRequest());
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setRequestURI("/service/agent/onbreak");
request.setContent(json.getBytes());
request.setContentType("application/json");
Map<String, String> pathVars = new AntPathMatcher().extractUriTemplateVariables(
"/service/agent/{function}", "/service/agent/onbreak");
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathVars);
MockHttpServletResponse response = new MockHttpServletResponse();
inboundGateway.handleRequest(request, response);
Assert.assertEquals(HttpStatus.OK.value(), response.getStatus());
verify(mockAgentService, times(1)).onBreak(any(AgentOnBreakRequest.class));
}
My issue with the above method is that I need to apply set the pathVars on the mock request. I have been trying unsuccessfully to use the MockMvc classes. I was at the point where I could submit the json payload successfully however it is not being passed on to the http inbound channel adapter.
Spring config:
<int-http:inbound-channel-adapter channel="http.incoming.agent.request.channel" supported-methods="POST"
path="service/agent/{function}">
<int-http:header name="function" expression="#pathVariables.function"/>
</int-http:inbound-channel-adapter>
<int:router input-channel="http.incoming.agent.request.channel" expression="headers.function">
<int:mapping value="onbreak" channel="asl.agent.convert.on.break" />
</int:router>
<int:json-to-object-transformer input-channel="asl.agent.convert.on.break"
output-channel="asl.agent.request.channel"
type="agent.dto.AgentOnBreakRequest"/>
<int:payload-type-router input-channel="asl.agent.request.channel">
<int:mapping channel="request.asl.agent.on.break" type="com.mhgad.za.vitel.server.agent.dto.AgentOnBreakRequest"/>
</int:payload-type-router>
<int:service-activator input-channel="request.asl.agent.on.break" output-channel="asl.agent.response.channel"
ref="agentService" method="onBreak" />
<bean id="agentService" class="service.agent.impl.AgentServiceImpl"/>
<mvc:annotation-driven/>
<mvc:default-servlet-handler default-servlet-name="AgentService"/>
<mvc:view-controller path="/*" view-name="initialView" />
Test code:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration("test/resources/webapp")
#ContextConfiguration(locations = {"classpath:spring/agent-integration.xml", "classpath:spring/agent-beans.xml",
"classpath:spring/test-router-config.xml"})
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class AgentOnBreakRouteTest {
#Autowired
private WebApplicationContext webCtx;
#Test
public void successful() throws JsonProcessingException, Exception {
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(createRequest());
MockMvc mvc = webAppContextSetup(webCtx).build();
mvc.perform(post("service/agent/onbreak").content(json)).andExpect(status().isOk());
}
}
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<servlet>
<servlet-name>aslAgentGateway</servlet-name>
<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>aslAgentGateway</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
log:
08:55:25.121 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - DispatcherServlet with name '' processing POST request for [service/agent/onbreak]
08:55:25.124 [main] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path service/agent/onbreak
08:55:25.124 [main] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Did not find handler method for [service/agent/onbreak]
08:55:25.124 [main] DEBUG o.s.i.h.i.IntegrationRequestMappingHandlerMapping - Looking up handler method for path service/agent/onbreak
08:55:25.125 [main] DEBUG o.s.i.h.i.IntegrationRequestMappingHandlerMapping - Did not find handler method for [service/agent/onbreak]
08:55:25.125 [main] WARN o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [service/agent/onbreak] in DispatcherServlet with name ''
08:55:25.126 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Successfully completed request
Judging from the log, the dispatcher cannot route the request to the inbound channel. Can anyone advise me on how to accomplish this? I have looked through various examples and postings but have come up short so far.

Deferred Result in Spring MVC returning incorrect response

I am using spring mvc 3.2.4 and jquery 1.9.0 for long polling. My application is deployed on Tomcat 7.0.42. My spring configuration files are as below:
Application Web.xml
<web-app 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"
version="3.0">
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/app-servlet.xml
</param-value>
</context-param>
</web-app>
Spring Configration xml as:-
<?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:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:annotation-config/>
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<context:component-scan base-package="com.webchat"/>
<bean id="defferedResult" class="com.exp.DeferredResultContainer"></bean>
</beans>
Controller for Posting data looks as
#RequestMapping(value = "/postComment", method = RequestMethod.POST)
public #ResponseBody String postComment(HttpServletRequest request) {
deferredResultContainer.updateAllResults(request.getParameter("comment"));
return "success";
}
Deferred Result container class
public class DeferredResultContainer {
private final Set<DeferredResult<String>> deferredResults = Collections.synchronizedSet(new HashSet<DeferredResult<String>>() );
public void put(DeferredResult<String> deferredResult){
deferredResults.add(deferredResult);
}
public void updateAllResults(String value){
for (DeferredResult<String> deferredResult : deferredResults){
deferredResult.setResult(value);
}
}
public void remove(DeferredResult<String> deferredResult){
deferredResults.remove(deferredResult);
}
public int determineSize(){
return deferredResults.size();
}
}
Controller for Deferred Result looks as
#RequestMapping(value = "/getComments", method = RequestMethod.GET)
#ResponseBody
public DeferredResult<String> getComments() throws Exception{
final DeferredResult<String> deferredResult= new DeferredResult<String>();
deferredResultContainer.put(deferredResult);
deferredResult.onTimeout(new Runnable() {
#Override public void run() {
deferredResultContainer.remove(deferredResult);
}
});
deferredResult.onCompletion(new Runnable() {
#Override public void run() {
deferredResultContainer.remove(deferredResult);
}
});
return deferredResult;
}
When I am trying to long poll it through ajax i am getting following response :-
{"setOrExpired":false}
And onCompletion method is also not getting executed.
To Simply things below controller gives perfect response as
{"1":"2"}
#RequestMapping(value = "/test1", method = RequestMethod.GET)
#ResponseBody
public Map test1() throws Exception{
Map m1 = new HashMap<String, Object>();
m1.put("1", "2");
return m1;
}
Once i change it to below and add Deferred result i get response as
{"setOrExpired":true}
#RequestMapping(value = "/test", method = RequestMethod.GET)
#ResponseBody
public DeferredResult<Map> test() throws Exception{
DeferredResult<Map> result = new DeferredResult<Map>();
Map m1 = new HashMap<String, Object>();
m1.put("1", "2");
result.setResult(m1);
return result;
}
Polling code
$(document).ready(function() {
longPoll();
function longPoll(){
$.support.cors = true;
var path = "http://localhost:8080/WebChatExp/rest";
$.ajax({
url: path + "/getComments",
cache:false,
success: function(data){
//To Do
alert("Data" + JSON.stringify(data));
},
error: function(err, status, errorThrown ) {
},
type: "GET",
dataType: "json",
complete: longPoll,
timeout: 60000 // timeout every one minute
});
}
I have searched various examples but cannot figure out if any extra configuration is required for deferred result. Please advise.
The response body you are getting
{"setOrExpired":true}
indicates that Spring serialized your DeferredResult (which has various properties including setOrExpired) to JSON instead of handling it with a DeferredResultMethodReturnValueHandler. In other words, it used another HandlerMethodReturnValueHandler, most likely RequestResponseBodyMethodProcessor (which handles #ResponseBody), to handle the value returned from your #RequestMapping annotated handler method. (The simplest way to test this is to see what happens when you remove the #ResponseBody annotation.)
Looking at the 3.2.x source code of RequestMappingHandlerAdapter, which registers the default HandlerMethodReturnValueHandler instances, the DeferredResultMethodReturnValueHandler is registered before RequestResponseBodyMethodProcessor and therefore will handle the DeferredResult return value first.
Since you're seeing different behavior, we must assume your configuration is not what you've shown here. (Note that <mvc:annotation-driven/> registers a RequestMappingHandlerAdapter.)
Also note that you are currently loading the configuration in /WEB-INF/app-servlet.xml twice, once by the ContextLoaderListener and once by the DispatcherServlet.
Get rid of your ContextLoaderListener and the corresponding context-param entirely. They are not needed in your example.
I know is impossible to be the problem in this case (spring mvc 3.2.4) but just for future references:
I get the same issue with spring boot 2.2.0.BUILD-SNAPSHOT (spring 5.1.5).
This error happens when you try to return DeferredResult using webflux instead of the traditional spring mvc app. Remember, in the new webflux api you should use mono/flux, not DeferredResult.

Categories

Resources