Spring MVC with ajax request - ajax

I'm requesting data from controller through ajax, but it can't convert json object to java object. I'm using jackson 2.2.3 and Spring 4.0.0. Could you help me find out where I did wrong? Thanks.
part of epscms-servlet.xml:
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name= "messageConverters" >
<list>
<ref bean="jacksonMessageConverter" />
</list>
</property>
</bean>
ajax request:
var data = {
orderId:1,
parentId:0,
className:"test",
newsType:1
};
$.ajax({
url : "${pageContext.request.contextPath}/classification/add/batch",
type : "POST",
data : data,
dataType: "json",
contentType: 'application/json',
success : function(data) {
alert("success");
},
error : function(data, status){
alert(data + status);
}
}
);
controller:
#RequestMapping(value="/add/batch", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
public String batchAdd(#RequestBody Classification c){
return "failure";
}
Classification.java
public class Classification {
private int orderId;
private String className;
private int parentId;
private int newsType;
//getters and setters..
}
if i change the controller method to
public String batchAdd(#RequestBody String cla){
return "failure";
}
it work fine, and I can get the json string. Did anyone else meet this question before?

You may need to JSON.stringify() your data before posting it to the endpoint:
...
type : "POST",
data : JSON.stringify(data),
dataType: "json",
...
Here is some additional info on stringify. Depending on which browsers you need to support, you may also want to read this

Related

AJAX get returns 404 in Spring

help me
index.jsp
$("#btn-submit").click(function () {
var username=document.getElementById("username");
var password=document.getElementById("password");
$.ajax({
url:"login",
contentType: 'application/json;charset=utf-8',
dataType: 'text',
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
data: {
username:username.value,
password:password.value
},
type: 'get',
success: function (response) {
if (response=="1") {
alert(response);
}
else alert(response);
},
error: function (x, e) {
console.log(e)
}
});
});
LoginController.java
#RequestMapping("/login")
#Controller
public class LoginController {
#Autowired
private UserService userService;
#RequestMapping(value = { "/login" }, method = RequestMethod.GET)
#ResponseBody
public int checkValid(#RequestParam("username") String username,#RequestParam("password") String password, HttpServletRequest request, HttpServletResponse response, Locale locale, Model model){
try {
if (userService.findByUserName(username).equals(hashPass(password))){
return 1;
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return 0;
}
return 0;
}
public String hashPass(String pass) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashInBytes = md.digest(pass.getBytes(StandardCharsets.UTF_8));
// bytes to hex
StringBuilder sb = new StringBuilder();
for (byte b : hashInBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}
spring-config-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
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.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
/WEB-INF/pages/
.jsp
/resources/jdbc.properties
<!-- Enable Annotation based Declarative Transaction Management -->
<tx:annotation-driven proxy-target-class="true"
transaction-manager="transactionManager" />
<!-- Creating TransactionManager Bean, since JDBC we are creating of type
DataSourceTransactionManager -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="postsDAO" class="com.blog.dao.impl.PostsDAO">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="postsService" class="com.blog.service.impl.PostsService">
<property name="postsDAO" ref="postsDAO"/>
</bean>
<bean id="userDAO" class="com.blog.dao.impl.UserDAO">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="userService" class="com.blog.service.impl.UserService">
<property name="userDAO" ref="userDAO"/>
</bean>
I use tomcat 9
Error:Failed to load resource: the server responded http://localhost:8080/Blog_war_exploded/login?username=root&password=root with a status of 404 ()
Look at your error: You are accessing http://localhost:8080/Blog_war_exploded/login but you actually want to access http://localhost:8080/login.
The reason is that you specified your URL as login instead of /login, so it is relative to the current "directory" and not to the root.
Changing the code to use /login should fix it:
$.ajax({
url: "/login",
...
})
On a side note, it's not a good idea to this via GET requests - among other things, the password will be stored in the server log in clear text. You should use a POST request instead.
Update:
Also, it seems you are use two request mappings for /login on top of each other, so you'll end up with /login/login. Check out how to use #RequestMapping properly.
Try changing the second (method-level) one to #RequestMapping(value = { "/" }, method = RequestMethod.GET) or just #RequestMapping("/").
I think the issue is related to your RequestMapping definition on both controller level and method level.
the first login at the controller level, means if you want to access any services in this controller, your requests have to start with "/login"
#RequestMapping("/login")
#Controller
public class LoginController {
and the second login at the method level, means you want to call the /login service under /login.
#RequestMapping(value = { "/login" }, method = RequestMethod.GET)
#ResponseBody
public int checkValid(#RequestParam("username") String username,#RequestParam("password") String password, HttpServletRequest request, HttpServletResponse response, Locale locale, Model model){
So the valid URL to call the /login service under /login controller is: /login/login
and because of this, your url /login was not found
you can either remove the first /login at the controller level, or use the /login/login from your ajax request...

AJAX returns 404 in Spring MVC

ViewResolver (my jsp is in the right folder as specified on prefix value):
<!-- Resolves views selected for rendering by #Controllers -->
<!-- to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
Servlet mapping:
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>*.fst</url-pattern>
</servlet-mapping>
Controller:
#Controller
public class HomeController {
private static final Logger logger =
LoggerFactory.getLogger(HomeController.class);
#RequestMapping("/home")
public ModelAndView home(String user, HttpServletRequest request) {
logger.info("Home controller has been executed");
ModelAndView mv = new ModelAndView();
mv.addObject("userName", user);
mv.addObject("controllerName", request.getRequestURI());
mv.setViewName("home");
return mv;
}
#RequestMapping(value = "/testAjax", method = RequestMethod.POST)
public String testAjax(#RequestParam("memberId") String id,
HttpServletRequest request, HttpServletResponse response,
Locale locale, Model model) {
logger.info("Text Ajax action has been executed. My Parameter is " + id);
return id;
}
}
After turning on Tomcat 8 server on STS IDE, accessing this web with this url http://localhost:8080/home.fst works okay.
But on the page, calling AJAX like below throws a 404 error:
$.ajax({
type: "POST",
url: "/testAjax.fst",
data: {"memberId" : "test"},
success: function (result) {
console.log(result)
}
});
This is console error log:
POST http://localhost:8080/testAjax.fst 404 (Not Found)
k.cors.a.crossDomain.send jquery-2.1.3.min.js:4
n.extend.ajaxhome.fst:11 (anonymous function) jquery-2.1.3.min.js:3
n.event.dispatch jquery-2.1.3.min.js:3
r.handle
Strange thing is that it calls testAjax controller just fine and there's no error log on server.
logger.info("Text Ajax action has been executed. My Parameter is " + id);
When textAjax action is invoked by my AJAX, the log is printed as well. I checked it out with debug point too (it broke alright).
What seems to be the matter??
Everything's good just Add #ResponseBody annotation in your method and also I suggest you to change your request method POST to GET
Spring
#RequestMapping(value = "/testAjax", method = RequestMethod.GET) //Made Change
#ResponseBody //added
public String testAjax(#RequestParam("memberId") String id, HttpServletRequest request, HttpServletResponse response, Locale locale, Model model) {
logger.info("Text Ajax action has been executed. My Parameter is " + id);
return id;
}
JQuery
$.ajax({
type: "GET", //Made Change
url:"/testAjax.fst",
data: {"memberId" : "test"},
success: function (result) {
console.log(result)
}
});

Ajax call implementation with Controller interface in Spring

Currently I am on a legacy project of Spring mvc and annotations are not working on it.
I have to create an controller-action which will respond to an ajax call with JSON response.
I have created my controller by implementing Controller interface.
I am able to implement a jsp page with this but unable to tweek it for ajax call.
Taking help from link1 link2 link3
Xml configuration in action-servlet.xml
<bean id="jsonResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order"><value>1</value></property>
</bean>
<bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">
<property name="contentType">
<value>text/html</value>
</property>
</bean>
<bean id="myOwnController" class="com.myapp.webapp.action.MyOwnController" />
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<!-- list of inteceptor urls -->
</list>
</property>
<property name="mappings">
<props>
<prop key="/mytest">myOwnController</prop>
<!-- mapping for other controller actions -->
</props>
</property>
</bean>
Controller class
package com.myapp.webapp.action
public class myOwnController implements org.springframework.web.servlet.mvc.Controller
{
#Override
public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception
{
Map<String, Object> model = new HashMap<String, Object>();
model.put("success", "true");
return new ModelAndView("jsonView", model);
}
}
ajax call js method (in Prototype.js)
function myAjaxMethod(){
new Ajax.Request('${pageContext.request.contextPath}/jsonView', {
method:'get',
onSuccess: function(transport) {
var response = transport.responseText || "no response text";
alert("Success! \n\n" + response);
},
onFailure: function() { alert('Something went wrong...'); }
});
}
Also I am unable to understand that how the url in ajax call will get to know the this is the controller that should be called.Do I am missing any mapping?
Please help.
Here is an example for, how to call a spring MVC controller from ajax function
This is all done using annotation driven environment.
1) Need to make application annotation driven first and give your controller package there.
2) Add #RequestMapping to the fn that is going to be called from ajax fn, and provide maping URL to ajax fn 'url' attribute.
changes in p[om.xml
need to add, following library to convert and send response to ajax success in form of json.
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
changes in spring conf file
<context:component-scan base-package="com.beingjavaguys.controller" />
<mvc:annotation-driven />
controller code:
#RequestMapping(value = "/save", method = RequestMethod.POST, headers = { "Content-type=application/json" })
public #ResponseBody
Response saveData(#RequestBody Employee employee) {
System.out.println("First Name: " + employee.getFirstName());
System.out.println("Last Name: " + employee.getLastName());
System.out.println("Email: " + employee.getEmail());
System.out.println("Phone: " + employee.getPhone());
return new Response("1", "Done");
}
ajax function syntax
function doAjaxPost() {
var formData = JSON.stringify({
firstName : $('#firstName').val(),
lastName : $('#lastName').val(),
email : $('#email').val(),
phone : $('#phone').val()
});
$.ajax({
type : "POST",
url : "save",
data : formData,
contentType : 'application/json',
success : function(data) {
if (data.status == '1')
$('#status').html('Form data sent !');
else
$('#status').html('Error in sending data !');
}
});
}
Hope this helps.
Use a button instead of submit to prevent page load on submit form and call ajax fn onClick.
Finally I got a solution(not via Spring but via a dirty logic).
Warning : Never work on old Spring version project.
Solution : I rendered whole html response in ajax call, filter my data and parse into json.
action-servlet.xml
<bean id="myOwnController" class="com.myapp.webapp.action.MyOwnController" />
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<!-- list of inteceptor urls -->
</list>
</property>
<property name="mappings">
<props>
<prop key="/mytest.html">myOwnController</prop>
<!-- mapping for other controller actions -->
</props>
</property>
</bean>
Controller class
package com.myapp.webapp.action
public class myOwnController implement org.springframework.web.servlet.mvc.Controller
{
#Override
public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception
{
Map<String, Object> model = new HashMap<String, Object>();
model.put("name", "davy jones");
return new ModelAndView("mytest", model);
}
}
Calling jsp Ajax call
function createFreshdeskUser(){
new Ajax.Request('${pageContext.request.contextPath}/mytest.html', {
method:'get',
onSuccess: function(transport) {
var divIdWordLength=16;
var htmlData=transport.responseText;
var startIndex=htmlData.indexOf("<div id=\"mydiv\">");
var endHtmlData=htmlData.substring(startIndex+divIdWordLength , htmlData.length);
var endIndex=endHtmlData.indexOf("</div>");
var finalHtmlData=endHtmlData.substring(0,endIndex);
var jsonObj=eval ("(" + finalHtmlData + ")");
alert(jsonObj.name);
},
onFailure: function() { alert('Something went wrong...'); }
});
}
mytest.jsp
<head>
</head>
<body>
<div id="mydiv">{'name':'${name}'}</div>
</body>
</html>

Spring3 Unmarshalling XML to Java

I am having trouble connecting all the pieces that would allow xml sent from an ajax client to be unmarshalled into Java objects. I am using Jquery for the ajax client, Spring3, and JAXB. Here are the key components:
Ajax Client
function checkForNewActivities(activities) {
$j.ajax({
url: "upload/checkForNewActivities",
type: "POST",
async: true,
dataType: "xml",
data: ({activities:activities}),
contentType: "application/xml",
beforeSend: function() {
alert("sending ajax");
},
complete: function() {
alert("ajax sent");
},
success: function(data) {
alert("success");
},
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + errorThrown);
}
});
}
Spring Config
<bean id="marshallingConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<property name="marshaller" ref="jaxbMarshaller" />
<property name="unmarshaller" ref="jaxbMarshaller" />
<property name="supportedMediaTypes" value="application/xml"/>
</bean>
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
a bunch of java classes
</list>
</property>
</bean>
And here is the Spring Controller method that is the target:
#RequestMapping(value="/checkForNewActivities",headers="application/xml", method=RequestMethod.POST)
public #ResponseBody String uploadMultipleWorkouts(#RequestBody String activities) {
System.out.println(activities);
return "";
}
With the headers="application/xml" in the RequestMapping, this method never gets called. If I remove the headers param, then the method is called and dumping the activities to the console shows the escaped xml.
I am clearly missing how to connect this method to the spring config so that unmarshalling xml takes place.
The reason your println prints out escaped xml is because the data type of the variable activities is String. You'll want to create a class to hold that data which will be passed to the method so there is a structure into which JAXB may translate the xml.
For example, instead of
public #ResponseBody String uploadMultipleWorkouts(#RequestBody String activities) {
You would want
public #ResponseBody Activities uploadMultipleWorkouts(#RequestBody Activities activities) {
Where Activities is a class you have defined with appropriate getters and setters such that the xml data you're passing in can be assigned. If the request data and response data must be different then you can simply define two classes, Request and Response variants.
As for why using headers="application/xml" messes things up, try setting it to headers = {"content-type=application/xml"}

How to call #RequestMapping method of Controller having specified URL using AJAX

I'm very new to Spring and Portlet. I want to use jqgrid to show some list. I am trying to call a method in controller which is annoted with the #RequestMapping but the method is not being called
My Controller has following method
#Controller(value = "myController")
public class MyController {
#RequestMapping(value="/myURL",method=RequestMethod.GET)
public #ResponseBody MyDTO initItemSearchGrid(RenderResponse response, RenderRequest request){
MyDTO myDto=new MyDTO();
return myDto;
}
}
My JSP code using AJAX
var urlink="/myURL"; /* myURL is the exact String written in value Attribute of
resourceMapping in Controller*/
$.ajax({
url :urlink,
cache: false,
data:$('#myForm').formSerialize(),
dataType: "json",
type: "GET",
contentType: "application/json; charset=utf-8",
success: function(jsondata){
...
}
});
When above AJAX code is executing my method is not called.
You mention Portlets in your question. Working with Spring and portlets is a bit different from servlets.
So, assuming you have a portlet like this
#Controller
#RequestMapping("VIEW") // VIEW mapping (as opposed to EDIT)
public class MyPortlet {
#RenderMapping
public ModelAndView handleRenderView(RenderRequest request, RenderResponse response) {
ResourceURL resourceUrl = response.createResourceURL();
resourceUrl.setResourceID("myResource"); // this is the id used to reference a #ResourceMapping
ModelAndView ret = new ModelAndView("myPortlet");
ret.addObject("resourceUrl", resourceUrl.toString());
return ret;
}
#ResourceMapping("myResource")
public void handleMyResource(ResourceRequest request, ResourceResponse response) {
OutputStream out = response.getPortletOutputStream();
// write whatever to output
}
}
As you can see, the #ResourceMapping is identified by a resource ID. The url for the resource mapping can be created using the standard portlet API methods and classes createResourceURL() and javax.portlet.ResourceURL.
If you prefer to use the portlet taglibrary instead, you can also generate a resource URL using the <portlet:resourceRequest> tag.
Your view might look something like this
myPortlet.jsp
...
<script>
$.ajax({
url :${resourceUrl},
cache: false,
data:$('#myForm').formSerialize(),
dataType: "json",
type: "GET",
contentType: "application/json; charset=utf-8",
success: function(jsondata){
.........
.........
.........
}
});
</script>
...

Resources