I am using Spring MVC with the Jackson Processor. When a JSON request is sent to the server as a POST request, the #RequestBody is being deserialized into the object that I need. The problem comes when the GET request is sent, it actually displays Http 500 Internal Server error. The exception that is thrown is:
java.io.EOFException: No content to map to Object due to end of input
org.codehaus.jackson.map.ObjectMapper._initForReading(ObjectMapper.java:2022)
org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:1974)
org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1331)
org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readInternal (MappingJacksonHttpMessageConverter.java:135)
org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:154)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.readWithMessageConverters(HandlerMethodInvoker.java:633)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveRequestBody(HandlerMethodInvoker.java:597)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments (HandlerMethodInvoker.java:346)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
No emtpy strings are sent and the correct JSON is sent to the server. I am not sure why this is happening. Below is my code:
JSP - index.jsp
<%#page language="java" contentType="text/html"%>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$('#myForm').submit(function() {
var form = $( this ),
url = form.attr('action'),
userId = form.find('input[name="userId"]').val(),
dat = JSON.stringify({ "userId" : userId });
$.ajax({
url : url,
type : "GET",
traditional : true,
contentType : "application/json",
dataType : "json",
data : dat,
success : function (response) {
alert('success ' + response);
},
error : function (response) {
alert('error ' + response);
},
});
return false;
});
});
</script>
</head>
<body>
<h2>Application</h2>
<form id="myForm" action="/application/user/find" method="GET">
<input type="text" name="userId" value="user1">
<input type="submit" value="Submit">
</form>
</body>
</html>
As soon as I change the request type to POST in the JSP and the controller method everything seems to work correctly.
package com.web;
#Controller
#RequestMapping("/user/*")
public class UserController {
#RequestMapping(value = "find", method = RequestMethod.GET, headers = {"content-type=application/json"})
public #ResponseBody UserResponse save(#RequestBody User user) throws Exception {
UserResponse userResponse = new UserResponse();
System.out.println("UserId :" + " " + user.getUserId());
return userResponse;
}
beans.xml
<context:component-scan base-package="com.web"/>
<mvc:annotation-driven/>
<context:annotation-config/>
User.java
public class User implements Serializable {
private String userId;
public User() {
}
// Getters and setters
}
When a GET request is sent the broswer usually displays %%user%%. This is only an example. Does the Jackson processor will still read GET requests?
I don't know where the problem is. I hope you can help.
I read the following description on what the data parameter does in jQuey.ajax() does at http://api.jquery.com/jQuery.ajax/:
Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests. ....
So it is appended to the URL and there is no request body. That is a behaviour consistent with the GET semantics, if you want to post data use POST.
Related
I'm trying to call my Spring controller using Ajax and submitting a form.
Function always retrieves the error window. I tried changing the URL parameter to "/profile", "profile" or "PrivateAreaController/profile", but I keep getting the same error.
My main.js file and controller are placed in the following order:
-->Mainfolder
-->src
-->java
-->controller
-->PrivateAreaController.java
-->resources
-->static
-->js
-->main.js
My controller is called PrivateAreaController
Ajax Code
$('#sampleForm').submit(
function(event) {
var firstname = $('#firstname').val();
var lastname = $('#lastname').val();
var data = 'firstname='
+ encodeURIComponent(firstname)
+ '&lastname='
+ encodeURIComponent(lastname);
$.ajax({
type : "POST",
dataType: "json",
url : '#Url.Action("callingcontroller","PrivateAreaController")',
contentType: "application/json; charset=utf-8",
data : data,
success : function(response) {
alert( response );
},
error : function() {
alert("not working");
}
});
return false;
});
Spring code
#RequestMapping(value = "/profile", method = RequestMethod.POST)
public #ResponseBody
String processAJAXRequest(
#RequestParam("firstname") String firstname,
#RequestParam("lastname") String lastname ) {
String response = "";
System.out.println("working");
return response;
}
HTML form
<form id="sampleForm" method="post" action="/profile">
<input type="text" name="firstname" id="firstname"/>
<input type="text" name="lastname" id="lastname"/>
<button type="submit" name="submit">Submit</button>
</form>
EDIT:
I found the answer.. i needed to add
#CrossOrigin(origins = "http://localhost:8080")
before the #RequesMapping parameter and change the url parameter of the ajax call to url: 'http://localhost:8080/(your requestmapping parameter)
I found the answer.. i needed to add
#CrossOrigin(origins = "http://localhost:8080")
before the #RequesMapping parameter and change the url parameter of the ajax call to url: 'http://localhost:8080/(your requestmapping parameter)
This worked for me using springboot with thymeleaf, made small modification to one of the answers on this post How do you get the contextPath from JavaScript, the right way?
In the HTML
<html>
<head>
<link id="contextPathHolder" th:data-contextPath="#{/}"/>
<body>
<script src="main.js" type="text/javascript"></script>
</body>
</html>
THEN IN JS
var CONTEXT_PATH = $('#contextPathHolder').attr('data-contextPath');
$.get(CONTEXT_PATH + 'action_url', function() {});
What is error you are getting, Press F12 and go to Network tab and the press submit button now see the url, try adding url:"../your service URL..
Well. I never seen this part before.
#Url.Action("callingcontroller","PrivateAreaController")
I normally do like as below:
$.ajax({
type : "POST",
dataType: "json",
url : '/profile',
contentType: "application/json; charset=utf-8",
data : data,
success : function(response) {
alert( response );
},
error : function() {
alert("not working");
}
});
But it can have a problem with the contextPath.
So, What I do is adding 'request.getContextPath()/' as below:
$.ajax({
type : "POST",
dataType: "json",
url : '${request.getContextPath()}/profile',
contentType: "application/json; charset=utf-8",
data : data,
success : function(response) {
alert( response );
},
error : function() {
alert("not working");
}
});
The contextPath has the URL of your start page.
For instance, 'www.google.com' or 'www.naver.com'
But in general, Since I personally use the contextPath a lot, I make a value and keep it.
var context = ${request.getContextPath()};
Then, your code will look neat and easy to reuse.
And also you can figure it out with the error attribute.
error : function(err) {
console.log("not working. ERROR: "+JSON.stringify(err));
}
I hope this works out.
I have a JSP page (client-side)
<form action="http://localhost:8080/REST-WS/rest/token" method="POST">
<label for="email">Email</label>
<input name="email" />
<br/>
<label for="password">Password</label>
<input name="password" />
<br/>
<input type="submit" value="Submit" />
</form>
It points to a function in REST Web Service (server-side)
#POST
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Code verify(#FormParam("email") String email,
#FormParam("password") String password,
#Context HttpServletResponse servletResponse) throws IOException {
Code code = generateRandomCode(email,password);
return token;
}
The problem is I want to give response to the client side containing the random-generated code from the server side.
First, it will be redirected to another JSP page and then the client side can receive the random-generated code from server.
How do I do it?
The problem is that you can't send arbitrary Java objects in a redirect. You can however add the data into query parameters. For example
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response post(#FormParam("name") String name,
#FormParam("email") String email) {
String message = "Hello " + name + ". Your email is " + email;
URI uri = UriBuilder.fromPath("/index.jsp")
.queryParam("message", message)
.build();
return Response.seeOther(uri).build();
}
Here, you are building a URI from the location of the jsp page, and adding a query parameter to the end of the URI. So the redirect will go to
http://localhost:8080/index.jsp?message=<the message>
From the index.jsp page you can get the parameter with request.getParameter("message"). For example
<h1><%= request.getParameter("message") %></h1>
Another option to work with JSP and Jersey is to implement MVC, which Jersey provides support for. You can check out this answer, though the examples use Maven (to get all the required jars). If you are interested and don't know how to use Maven, let me know and I'll see if I can help you get all the jars you need.
UPDATE
Ajax Example.
Easiest Javascript library to get started with (if you have no experience) is jQuery. I won't really give much explanation about the code, that's kinda out of scope. I would go through some tutorials (W3Schools has some good getting started guides), and there are answers all over SO that can answer your questions.
Here's a complete working html page. Just change var url = "/api/submit"; to whatever endpoint you are sending the request to.
<!DOCTYPE html>
<html>
<head>
<title>Ajax Example</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script>
$(document).ready(function(){
var url = "/api/submit";
$("#submitBtn").click(function(e) {
e.preventDefault();
var formData = $("#nameForm").serialize();
$.ajax({
url: url,
data: formData,
dataType: "json",
type: "POST",
success: function(data) {
var message = data.message;
var date = data.date;
var h1 = $("<h1>").text(message);
var h3 = $("<h3>").text(date);
$("#content").empty()
.append(h1).append(h3);
},
error: function(jqxhr, status, errorMsg) {
alert(status + ": " + errorMsg);
}
});
});
});
</script>
</head>
<body>
<div id="content">
<form id="nameForm">
First Name: <input type="text" name="fname"/><br/>
Last Name : <input type="text" name="lname"/><br/>
<button id="submitBtn">Submit</button>
</form>
</div>
</body>
</html>
Here is the test resource class
#Path("submit")
public class FormResource {
public static class Model {
public String message;
public String date;
}
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Model post(#FormParam("fname") String fname,
#FormParam("lname") String lname) {
String message = "Hello " + fname + " " + lname;
Model model = new Model();
model.message = message;
model.date = new Date().toString();
return model;
}
}
You will need to make sure you have a JSON provider to handle the JSON Pojo serialization or it won't work (the Model won't be able to serizalize to JSON).
My related Request handling code as following
#RequestMapping(value = "/customer" , method = RequestMethod.GET)
public String customer(ModelMap modelMap , #RequestParam Integer age) {
modelMap.addAttribute("requestKey", "Hola!");
modelMap.addAttribute("age", age);
return "cust";
}
#RequestMapping(value = "/request" , method = RequestMethod.GET)
public String welcome(ModelMap modelMap , #RequestParam(value = "age" , required = false)Integer age) {
modelMap.addAttribute("requestKey", "Hola!");
modelMap.addAttribute("age", age);
return "request";
}
#RequestMapping(value = "/request" , method = RequestMethod.POST)
public String responseBody(ModelMap modelMap , final #RequestBody Student student){
modelMap.addAttribute("name", student.getName());
modelMap.addAttribute("lastname", student.getLastname());
modelMap.addAttribute("age", student.getAge());
return "request";
}
cust.jsp
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Customer</title>
</head>
<body>
<p>${age}</p>
</body>
</html>
request.jsp
<html>
<head>
<title>RequestBody</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
JSONTest = function() {
$.ajax({
url: "customer",
type: "get",
data: {
name: "Okan",
lastname: "Pehlivan",
age:22 },
dataType: "json"
});
};
</script>
</head>
<body>
<p>${requestKey}</p>
<h1>My jQuery JSON Web Page</h1>
<div id="resultDivContainer"></div>
<button type="button" onclick="JSONTest()">JSON</button>
</body>
</html>
I want to get request using ajax, and i have some parameters, (name=Okan e.g). I want to show any patameter on the cust.jsp. When i debug the code for welcome() metod, age assigned the my age. I mapped this value with its key "age". request.jsp file is not changed.
Ajax call will not change the view. It will return the parameters on same page in success : function(response) {} . If you wants to change the view, you need make non ajax GET call on a separate method and pass inline parameters like:
Controller:
#RequestMapping(value = "/customer/{name}/{lastname}/{age}" , method = RequestMethod.GET)
public String customer(#PathVariable(value = "name") String name, #PathVariable(value = "lastname") String lastname, #PathVariable(value = "age") String age) {
//code here
return "cust";
}
JSP
window.open("/customer/Okan/Pehlivan/22 ","_self");
It will return on cust.jsp
The request jsp is not changed because you are not changing it anywhere on the page after the AJAX call.
You do make a request but are not using the response.
Add a success function to your ajax call and then read the data there.
For example :
$.ajax({
url, data , dataType and method as is with an addition of the following :
success : function(responseText){
Set responseText to your <p>
}
});
For showing the age in cust.jsp, the request parameter needs to be passed while calling the url. something like : http://host-path/context-path/customer?age=69
Autoboxing should take care of int to Integer conversion for request parameter, if you see an exception try using int instead.
Some info that might be of help :
When using ${varName} in jsp / javascript, you need the model to
already have that data.
Consider using tags to control the out put of dynamic
variables, they may help.
When making ajax calls to request for data, process the response in a
handler and continue your logic from there.
HTH.
I have the following being passed from browser to server
Status Code:204 No Content
Request Method:POST
Content-Type:application/x-www-form-urlencoded
Form Data
json:{"clientName":"PACK","status":"success","message":"successful!"}
and in jsp code
var loginData = {
clientName: cList,
status: "success",
message: "successful!"
};
$.ajax({
url: subUrl,
type: 'POST',
contentType : "application/x-www-form-urlencoded",
data: {
json: JSON.stringify(loginData)
},
success: function (data) {
handleLoginResult(data);
}
});
And in Java code I have
#POST
public Object persistResetPasswordLogs(#FormParam("clientName")
String clientName) {
try {
log.info("in rest method ??? "+clientName);
.......
.......
In server I am getting clientName as null.
What could be the reason for this and how can I resolve this?
AFAIK, there is no Jersey (JAX-RS) mechanism to parse JSON into form data. Form data should be in the form of something like
firstName=Stack&lastName=Overflow (or in your case clientName=someName)
where firstName and lastName are generally then name attribute value in the form input elements. You can use jQuery to easily serialize the field values, with a single serialize() method.
So you might have something that looks more along the lines of something like
<form id="post-form" action="/path/to/resource">
Client Name: <input type="text" name="clientName"/>
</form>
<input id="submit" type="button" value="Submit"/>
<script>
$("#submit").click(function(e) {
$.ajax({
url: $("form").attr("action"),
data: $("form").serialize(),
type: "post",
success: processResponse,
contentType: "application/x-www-form-urlencoded"
});
});
function processResponse(data) {
alert(data);
}
</script>
Have you defined the Requestmapping like this:
#POST
#Path("/submitclient") // your request mapping for 'subUrl'
public Object persistResetPasswordLogs(#FormParam("clientName") String clientName)
and html:
<form action="submitclient" method="post">
...
</form>
Also look at your json object. I believe you should send something like this:
var loginData = {
clientName: "dit" // get it from input
};
?
I am using Spring MVC and JSP to send JSON to Spring MVC Controller. Actually, my JSON works for 1 method but does not work for another and I don't understand why. The code is below:
JSP - index.jsp
<%#page language="java" contentType="text/html"%>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$('#myForm').submit(function() {
var form = $( this ),
url = form.attr('action'),
userId = form.find('input[name="userId"]').val(),
dat = JSON.stringify({ "userId" : userId });
$.ajax({
url : url,
type : "POST",
traditional : true,
contentType : "application/json",
dataType : "json",
data : dat,
success : function (response) {
alert('success ' + response);
},
error : function (response) {
alert('error ' + response);
},
});
return false;
});
});
</script>
<script type="text/javascript">
$(function() {
$('#emailForm').submit(function() {
var form = $( this ),
url = form.attr('action'),
from = form.find('input[name="from"]').val(),
to = form.find('input[name="to"]').val(),
body = form.find('input[name="body"]').val(),
subject = form.find('input[name="subject"]').val(),
fileName = form.find('input[name="fileName"]').val(),
location = form.find('input[name="location"]').val(),
dat = JSON.stringify({ "from" : from,"to" : to,"body" : body,"subject" : subject,"fileName" : fileName,"location" : location });
$.ajax({
url : url,
type : "GET",
traditional : true,
contentType : "application/json",
dataType : "json",
data : dat,
success : function (response) {
alert('success ' + response);
},
error : function (response) {
alert('error ' + response);
},
});
return false;
});
});
</script>
</head>
<body>
<h2>Application</h2>
<form id="myForm" action="/application/history/save" method="POST">
<input type="text" name="userId" value="JUnit">
<input type="submit" value="Submit">
</form>
<form id="emailForm" action="/application/emailService/sendEmail" method="GET">
<input type="text" name="from" value="name#localhost.com">
<input type="text" name="to" value="user#localhost.com">
<input type="text" name="body" value="JUnit E-mail">
<input type="text" name="subject" value="Email">
<input type="text" name="fileName" value="attachment">
<input type="text" name="location" value="location">
<input type="submit" value="Send Email">
</form>
</body>
</html>
The 1st form works correctly and is deserilized in Spring MVC. A sample of that code is:
#Controller
#RequestMapping("/history/*")
public class HistoryController {
#RequestMapping(value = "save", method = RequestMethod.POST, headers = {"content-type=application/json"})
public #ResponseBody UserResponse save(#RequestBody User user) throws Exception {
UserResponse userResponse = new UserResponse();
return userResponse;
}
For the 2nd form I am getting exceptions:
#Controller
#RequestMapping("/emailService/*")
public class EmailController {
#RequestMapping(value = "sendEmail", method = RequestMethod.GET, headers = {"content-type=application/json"})
public void sendEmail(#RequestBody Email email) {
System.out.println("Email Body:" + " " + email.getBody());
System.out.println("Email To: " + " " + email.getTo());
}
}
Below is the stack trace:
java.io.EOFException: No content to map to Object due to end of input
org.codehaus.jackson.map.ObjectMapper._initForReading(ObjectMapper.java:2022)
org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:1974)
org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1331)
org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readInternal(MappingJacksonHttpMessageConverter.java:135)
org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:154)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.readWithMessageConverters(HandlerMethodInvoker.java:633)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveRequestBody(HandlerMethodInvoker.java:597)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:346)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
I have tried using the POST too, but still the same problem. I need to use JSP to send JSON data to the Spring MVC Controller.
I am not sure where the problem is.
beans.xml
<context:component-scan base-package="com.web"/>
<mvc:annotation-driven/>
<context:annotation-config/>
Any ideas?
EDIT
public class Email implements Serializable {
private String from;
private String to;
private String body;
private String subject;
private String fileName;
private String location;
public Email() {
}
// Getters and setters
}
JSON sent is in form2 which is #emailForm.
You should check if you have set "content-length" header.
I ran into the same problem, but I used curl to verify the server side function.
The initial data section in my curl command is
-d "{'id':'123456', 'name':'QWERT'}"
After I changed the command to
-d '{"id":"123456", "name":"QWERT"}'
then it worked.
Hope this gives some hints.
I had this problem when I tried to use POST method with path parameter, but I forgot to put '#PathParam("id") Integer id', I just had 'Integer id ' in parameters.