I'm trying to get a string response from my controller but I get the below error:
SyntaxError: Unexpected end of JSON input(…) "Error 200"
When I change the response to a boolean or a different type, it's working ok. The problem is when I try to return a string.
js code:
$.ajax({
method: "POST",
url: "./signup",
data: _data,
dataType: "json",
contentType : "application/json;charset=UTF-8",
success : function(data) {
console.log(data)
},
error : function(qXHR, textStatus, errorThrown){
console.log(errorThrown, "Error " + qXHR.status);
}
});
controller code:
#RequestMapping(value = "/signup", method = RequestMethod.POST, produces = {"text/plain", "application/*"})
public #ResponseBody String signup(#RequestBody UserSignup details) {
//...
return message;
}
any idea how can I solve this problem? I have tried a few things but nothing work. I think the response format is wrong as what the code expects.
Edit
I have changed my code(removed produces) but I still getting the same error:
SyntaxError: Unexpected end of JSON input(…) "Error 200"
#RequestMapping(value = "/signup", method = RequestMethod.POST)
public #ResponseBody String signup(#RequestBody UserSignup details) {
message = "ok";
}
return message;
}
Your method is wrong. You are saying to produce produces = {"text/plain", "application/*"} But you are also adding the #ResponseBody which will generate JSON format response.
I would suggest you remove the attribute produces. And verify the string you are returning is well formed
Try to wrap your response in ResponseEntity class
#RequestMapping(value = "/signup", method = RequestMethod.POST)
public #ResponseBody ResponseEntity<String> signup(#RequestBody UserSignup details) {
message = "ok";
return new ResponseEntity<>(message, HttpStatus.OK);
}
Also double check data that you are sending to server, maybe this is the problem, can you show us _data value?
As I don't have problem when the response is different stuff as a String I have solved the problem creating my own object. So below is the code:
public class Response<T> {
private T message;
private Exception ex;
public Exception getEx() {
return ex;
}
public void setEx(Exception ex) {
this.ex = ex;
}
public T getMessage() {
return message;
}
public void setMessage(T message) {
this.message = message;
}
}
#Controller
public class MyControllerController {
private Response<String> _response;
private String message;
public MyController() { _response = new Response<>(); }
#RequestMapping(value = "/signup", method = RequestMethod.POST)
public #ResponseBody Response<String> signup(#RequestBody UserSignup details) {
try{
message = "";
// code...
_response.setMessage(message);
return _response;
}catch (Exception ex){
_response.setEx(ex);
return _response;
}
}
}
response example in the browser:
Object {message: "", ex: null}
Related
I´m having some issues when returning some errors from a rest WebService.
Making a request with the header {"Accept":"application/octet-stream"}
(the service returns a document ResponseEntity<InputStreamResource> if all the process goes well).
When all the process goes well the document is downloaded fine, but when an error is occurred and the code jumps to the #ControllerAdvice and tries to return a JSON error. Here comes the problem, when trying to return the JSON springs crashes:
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
Here is a example of some code:
Controller
#RequestMapping(value = "/test", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_OCTET_STREAM_VALUE })
public ResponseEntity<CustomError> test() throws Exception {
throw new Exception();
}
ControllerAdvice
#ControllerAdvice
public class ExceptionHandlerAdvice {
private static final Logger logger = LogManager.getLogger(ExceptionHandlerAdvice.class);
#ExceptionHandler({Exception.class,Throwable.class})
#ResponseBody
public ResponseEntity<CustomError> handleUnhandledException(Exception exception) {
CustomError error = new CustomError(exception.getMessage());
return new ResponseEntity<CustomError>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
CustomError:
public class CustomError {
private String errorDescription;
public CustomError(String errorDescription) {
super();
this.errorDescription = errorDescription;
}
public String getErrorDescription() {
return errorDescription;
}
public void setErrorDescription(String errorDescription) {
this.errorDescription = errorDescription;
}
}
I´ve also tried returning new headers on #controllerAdvice
#ExceptionHandler({Exception.class,Throwable.class})
#ResponseBody
public ResponseEntity<CustomError> handleUnhandledException(Exception exception) {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
CustomError error = new CustomError(exception.getMessage());
return new ResponseEntity<CustomError>(error,headers, HttpStatus.INTERNAL_SERVER_ERROR);
}
Any idea how can I make this work or ignore Accept header on response?
It´s possible?
Thanks in advance
This exception means your response type not match with your request header. If you are expecting JSON/Stream to be returned, your request header should be {"Accept":"application/octet-stream,application/json"}.
I have problem with convert JSON to Java class.
Controller
#RequestMapping(value = "/{username}/add", method = POST)
public void add(#RequestBody NoteModel note) {
System.out.println(note.getTitle());
}
JSON
{
title : "Title",
text : "Text"
}
NoteModel
public class NoteModel {
private String title;
private String text;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
So, when I send json to the controller, Controller see same url, but can't deserialize JSON to Java (I think). Because, when I try, to send JSON - { title : "Title" }, and controller wait argument - #RequestBody String note, it can easily display it.
I'm try to do, what was in https://gerrydevstory.com/2013/08/14/posting-json-to-spring-mvc-controller/ and include adapter in servlet.xml, but was the same effect.
AJAX
$.ajax({
type : "POST",
contentType : "application/json; charset=utf-8",
url : window.location.pathname,
data : JSON.stringify({
title : $("#titleId").val(),
text : $("#textId").val()
}),
success: function () {
$("#titleId").val("");
$("#textId").val("");
}
})
Add #RequestMapping(value = "/{username}/add", method = POST, produces = "application/json")
Make sure that you have added content-type to "application/json" in header of your request.
how to catch the problem:
Send the String to your controller and try to create your object. Put breakpoint to objectMapper.readValue() and check what is the exactly problem;
#RequestMapping(value = "/{username}/add", method = POST)
public void add(#RequestBody String note) {
ObjectMapper objectMapper = new ObjectMapper();
NoteModel noteModel = objectMapper.readValue(result, NoteModel.class);
}
I think that there is some conflict between default ObjectMapper and JSON mapper logic.
Java - spring controller - Angularjs form submission
Problem is with "#RequestBody OfferForm data" when i submit form i get error "404 bad request" but when i replace OfferForm bean with String object it works fine and display form data in json format.
any help appreciated.
Following is my angularjs function code
$scope.submitOffer = function() {
alert('submitOffer')
$http({method: 'POST', url: '/offer/submitOffer', data: $scope.formData}).
success(function(data, status, headers, config) {
$scope.successMsg = data;
}).
error(function(data, status, headers, config) {
if(status == 400) {
$scope.errMessages = data;
} else {
alert('Unexpected server error.');
}
});
};
Following is my controller code
#RequestMapping(value="offer")
public class OfferController{
#RequestMapping(value = "/submitOffer", method = RequestMethod.POST)
#ResponseBody public ResponseEntity<?> postForm(#RequestBody OfferForm data) {
System.out.println(data);
return new ResponseEntity<String>("Offer Created", HttpStatus.OK);
}
}
Following is my java bean
public class OfferForm {
private String offerType;
private String offerTitle;
public String getOfferType() {
return offerType;
}
public void setOfferType(String offerType) {
this.offerType = offerType;
}
public String getOfferTitle() {
return offerTitle;
}
public void setOfferTitle(String offerTitle) {
this.offerTitle = offerTitle;
}
}
Your $scope.formData object has more property than expected by the webservice.
You should provide to your webservice an object which has at most two properties of type string: offerType and offerTitle.
I think you currently have more properties than expected or you don't have the correct type, thus the bad request exception.
You could do something like that in your javascript, given that the two properties are a string:
$scope.submitOffer = function () {
$http({
method: 'POST',
url: '/offer/submitOffer',
data: {
offerType: $scope.formData.offerType,
offerTitle: $scope.formData.offerTitle
}
}).
success(function (data, status, headers, config) {
$scope.successMsg = data;
}).
error(function (data, status, headers, config) {
if (status == 400) {
$scope.errMessages = data;
} else {
alert('Unexpected server error.');
}
});
};
I get following response when I try to delete: 405 Method Not Allowed.
In my logs there is written that GET is allowed, but DELETE isn't.
Java:
#ResponseBody
#RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
public void delete(#PathVariable String id) {
speakerService.delete(id);
}
Angularjs
app.factory('SpeakerResource', function ($resource) {
return $resource('rest/speaker/:speakerId',
{
speakerId: '#speakerId'
},
{
'update': { method: 'PUT' }
},
{
'delete': { method: 'DELETE', params: { 'id': 'speakerId' }}
}
)
});
SpeakerService
this.delete = function (id, callback) {
SpeakerResource.delete({ speakerId: id }, function () {
callback();
});
}
I do not know your complete code, and I am not an expert in AngularJS, but it looks like your want to send a DELETE request to the URL <hopefullySomething>/{id} (Path variable). But it looks like that you send a DELETE request so some URL with an parameter id <hopefullySomething>?id={id} (Request parameter).
This question and answers explain the difference between path variable and request parameters a bit more #RequestParam vs #PathVariable
use $http.delete(), and return data for example status, I just tested the following with spring and working correctly
#RequestMapping(value = "delete/{id}", method = RequestMethod.DELETE)
public #ResponseBody Status deletePerson(#PathVariable("id") int id) {
try {
personService.removePerson(id);
return new Status(1, "person deleted Successfully !");
} catch (Exception e) {
return new Status(0, e.toString());
}
}
angular
angular.module('personService', [])
.factory('Person', ['$http',function($http) {
return {
deletePerson: function(id) {
return $http.delete('/restperson/delete/'+id);
}
}
}]);
controller
angular.module('personController', [])
// inject the person service factory into our controller
.controller('mainController', ['$scope','$http','Person', function($scope, $http, Person) {
//delete
$scope.deletePerson = function(id) {
Person.deletePerson(id)
.success(function(data) {
$scope.message = data;
});
};
}]);
I am using Spring MVC and returning JSON as response. I would like to create a generic JSON response where I can put in any TYPE and want the response to look like this
{
status : "success",
data : {
"accounts" : [
{ "id" : 1, "title" : "saving", "sortcode" : "121212" },
{ "id" : 2, "title" : "current", "sortcode" : "445566" },
]
}
}
So I created a Response<T> object
public class Response<T> {
private String status;
private String message;
T data;
...
...
}
Is this the correct way of doing this, or is there a better way?.
How do you use this Response object in Spring controller to return an empty response object and/or a populated response object.
Thanks in advance GM
UPDATE:
In order to get the similar JSON output as the one described, i.e. with "accounts" key in JSON, I had to use Response<Map<String, List<Account>>> the following in the controller:
#RequestMapping(value = {"/accounts"}, method = RequestMethod.POST, produces = "application/json", headers = "Accept=application/json")
#ResponseBody
public Response<Map<String, List<Account>>> findAccounts(#RequestBody AccountsSearchRequest request) {
//
// empty accounts list
//
List<Account> accountsList = new ArrayList<Account>();
//
// response will hold a MAP with key="accounts" value="List<Account>
//
Response<Map<String, List<Account>>> response = ResponseUtil.createResponseWithData("accounts", accountsList);
try {
accountsList = searchService.findAccounts(request);
response = ResponseUtil.createResponseWithData("accounts", accountsList);
response.setStatus("success");
response.setMessage("Number of accounts ("+accounts.size()+")");
} catch (Exception e) {
response.setStatus("error");
response.setMessage("System error " + e.getMessage());
response.setData(null);
}
return response;
}
Is this the right way of doing this? i.e. in order to get the "accounts" key in JSON output?
While your example JSON is not valid (status and data are not enclosed in quotations), this approach will work.
You will want to ensure that you have the Jackson jars on your classpath, and Spring will take care of the rest.
To get this to work, I would create a constructor for your response class that looks something like this:
public class Response<T> {
private String status;
private String message;
private T data;
public Response(String status, String message, T data) {
this.status = status;
this.message = message;
this.data = data;
}
//...getter methods here
}
And then in your Spring controller, you just return this object from your method that is mapped with #RequestMapping
#Controller
public class MyController {
#RequestMapping(value="/mypath", produces="application/json")
public Response<SomeObject> myPathMethod() {
return new Response<SomeObject>("200", "success!", new SomeObject());
}
}