Spring Controller + Ajax return String - ajax

I want to return String from Spring MVC Controller to Ajax.
It is not working as expected and gives error.
My Ajax codes for this:
function ajaxRequest(item) {
$.ajax({
type: "POST",
url: "/myPage",
data: {
item: item
},
success: function (html) {
alert(html);
},
error: function(e) {
console.log("Error:" + e);
}
});
}
My Controller:
#RequestMapping(value = "/myPage", method= RequestMethod.POST, produces="text/plain")
public #ResponseBody String myController(HttpServletRequest request) {
String myItem = request.getParameter("item");
...
return myItem + "bla bla bla";
}
Chrome console result:
POST http://localhost:8080/myPage 406 (Not Acceptable) jquery.js
Error:[object XMLHttpRequest]
What am i missing here?

When you return a String from a handler method annotated with #ResponseBody, Spring will use a StringHttpMessageConverter which sets the return content-type to text/plain. However, your request does not have an Accept header for that content-type so the Server (your Spring app) deems it unacceptable to return text/plain.
Change your ajax to add the Accept header for text/plain.

I have solved it. We can return correct values with response writer.
#RequestMapping(value = "/myPage")
public void myController(HttpServletRequest request, HttpServletResponse response) throws IOException {
String myItem = request.getParameter("item");
...
response.getWriter().println(myItem + "bla bla bla");
}

Be sure that you have Jackson dependency. Spring MVC can relies on it.

Related

How to send JSON response from controller?

I want to pass a boolean value from my controller to javascript using json but couldnot find a way as I am new to spring mvc.
While using servlet we wrote:
response.getWriter().println(somevalue)
and the somevalue can be received using ajax.
Here my controller method is:
#RequestMapping(value = REGISTERACTION , method = RequestMethod.POST)
#ResponseBody
public boolean RegisterUser(#ModelAttribute("register") Register register,HttpServletRequest request, HttpServletResponse response)
{
boolean Registrationsuccess = userService.RegisterUser(register);
return Registrationsuccess;
}
So, here the boolean variable is Registrationsuccess which I want to send to js file and receive it using ajax.
And in my javascipt function which is called using onsubmit event-->
function AccountExists()
{
$.ajax({
type: 'POST',
url: 'registerProcess',
success: function(data){
let detail = JSON.parse(data);
if( data == true)
alert("Success");
else
alert("Not ");
}
});
}
Getting error --
The target resource does not have a current representation that would be acceptable to the user agent, according to the proactive negotiation header fields received in the request, and the server is unwilling to supply a default representation.
You need to use ResponseEntity and #RestController for JSON Response.
Note : #RestController includes both annotations #Controller and #ResponseBody.
Try with this :
#RestController
#RequestMapping("controller")
public class Controller {
#PostMapping("REGISTERACTION")
public ResponseEntity<Boolean> RegisterUser(#ModelAttribute("register") Register register)
{
Boolean registrationSuccess = userService.RegisterUser(register);
return new ResponseEntity<Boolean>(registrationSuccess , HttpStatus.OK);
}
}
Try to use #ResponseBody annotation in your controller's method. And change the return type of the method to Boolean, then return Registrationsuccess instead of ModelAndView.
You can achieve this using 2 approach
Approach 1: Set model attribute and using expression language you can find on jsp
model.addAttribute("test",true);
in Jsp page
${test}
Approach 2: If you are sending ajax request instead of ModelAndView create a object
set any attribute boolean and return object from method #ResponseBody annotation you will get json in Ajax Response
#RequestMapping(value = REGISTERACTION , method = RequestMethod.POST)
public #ResponseBody MyCustomObject RegisterUser(#ModelAttribute("register") Register register,HttpServletRequest request, HttpServletResponse response)
{
boolean Registrationsuccess = userService.RegisterUser(register);
MyCustomObject cusobj=new MyCustomObject();
cusobj.setStatus(true);
return cusobj;
}
Whatever code you have written it will not return json(It is basically form submission approach) so you have to go with first approach.

Sending file to Spring Boot REST using Axios

I am trying to send a csv file to my java spring boot backend. The code to send my file is below:
var url = 'http://localhost:3001/UploadFile';
var file = this.state.file;
var formData = new FormData();
formData.append("file", file);
axios.post(url, formData, {
headers: { 'Content-Type': 'multipart/form-data' }
});
And the code to accept my file from Spring Boot:
#CrossOrigin
#RequestMapping("/UploadFile")
#ResponseBody
public void uploadFile(#RequestParam("file") MultipartFile file) {
}
However, it doesn't seem to work. I keep getting an error saying that the 'Current request is not a multipart request'. Any ideas?
It's not sufficient to specify content-type in frontend you need to do it in controller as well.
You should tell to spring controller what it should consume and also it would be nice to set RequestMethod as POST like this:
#CrossOrigin
#RequestMapping("/UploadFile")
#ResponseBody
public void uploadFile(#RequestParam("file") MultipartFile file, method = RequestMethod.POST, consumes = "multipart/form-data") {
}

Error handling on controller SpringMVC

I am developing an application in jax-rs and spring mvc.
I want to notify my client each time when an default error is occured like
400, 403, 404, 405 and 415.
Controller
#Controller
#RequestMapping("/customer")
public class CustomerController {
#Autowired
CustomerService customerService;
// ........xxxxxx..............xxxxxxx................xxxxxxx.............//
#CrossOrigin
#RequestMapping(value = "/",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody String fetchCustomer() throws JsonProcessingException {
return new ObjectMapper().writeValueAsString(customerService.fetchAllCustomer());
}
// ........xxxxxx..............xxxxxxx................xxxxxxx.............//
}
Client
$http({
method: "GET",
contentType: "application/json",
url: baseUrl + '/customer'
}).success(function (response) {
console.log(response);
// you can also use
console.log(JSON.stringify(response);
}).error(function (response) {
console.log(response);
});
When i request a service from client i want to send response back with status code and custom message.
Example
When i defind method = post on controller and from client i send request as get service should return message like
error:{
Status Code: 405,
Message: Invalid Method
url: error/405
}
Check this out for reference.
Define a method for handling the specific error scenario and annotate it as #ExceptionHandler. The exception in your scenario (request method not supported) is HttpRequestMethodNotSupportedException.class. You can create more generic handler methods using Throwable, Exception etc.
In order to prevent duplication of error handling across controllers, one convenient way is to define all handlers in single class and use #ControllerAdvice on that. This way, all handlers will be applied to all controllers.
Do not return a String but return a org.springframework.http.ResponseEntity.
You can add status codes to this object
ResponseEntity<String> responseEntity = new ResponseEntity<String>("This is a response", HttpStatus.INTERNAL_SERVER_ERROR);
return responseEntity;
So your method signature will also change as below
#RequestMapping(value = "/", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody ResponseEntity<String> fetchCustomer() throws JsonProcessingException {
try {
String str = new ObjectMapper().writeValueAsString(customerService.fetchAllCustomer());
return new ResponseEntity<String>(str, HttpStatus.OK);
}
catch (Exception e) {
return new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
If there is an error, you can either use controller advice or catch the exception and update the ResponseEntity appropriately

Spring MVC Ajax form properties name

I have a form with a list of fields:
type, name, description, height ,width
I send by ajax to my controller, my controller receive this ajax call but he said that all input fields are null.
My mapped DTO have the same fields but with distinct name, really I don't need use the same name in my call ajax that in my #RequestBody dto class.
Its possible? I am limited to use same names in the class and the ajax calls?
This aren't a problem really, but I can't found any info about this.
My DTO properties:
ResourceCreateDTO [resourceTypeId=null, resourceId=null,
resourceName=null, resourceDescription=null, folderId=null]
My JSON data:
resource-description: "asdfasdfasdfasdfsadfasdfsdfasdfasdfasdfasdfsadfasdfasdf"
resource-folder: "0"
resource-folder-type: "1000"
resource-id: "1006"
resource-name: "asdfasdfasdfasdf"
My AJAX Call:
$("#createModalSubmit").click(function(){
var data = {};
$('#createForm *').filter(':input').each(function(){
var input = $(this);
data[input.attr("name")] = input.val();
delete data["undefined"];
});
$.ajax({
contentType : "application/json; charset=utf-8",
type: "POST",
url: context + "/editor/create",
data: JSON.stringify(data),
dataType : 'json',
cache: false,
success:function(result){
},
error:function(){
}
});
});
My Controller config:
#RequestMapping(value = "/editor/create", method = RequestMethod.POST)
public #ResponseBody ResourceDTO create(#RequestBody ResourceCreateDTO dto)
throws Exception {
System.out.println("dto: " + dto.toString());
This system out prints the above DTO toString.
I am searching any type of anotation or config that I can name the DTO properties:
#MyCustomName("resource-name")
private String resourceName;
Use my "resource-name" from the AJAX call.
If your DTO cannot have the same name that is being used in your ajax, you can then match it manually inside your controller.
#RequestMapping(value = "/editor/create", method = RequestMethod.POST)
public #ResponseBody ResourceDTO create(#RequestBody String dto)
throws Exception {
//mapping
}
Or
#RequestMapping(value = "/editor/create", method = RequestMethod.POST)
public #ResponseBody ResourceDTO create(#RequestBody Map<String,Object> dto)
throws Exception {
//mapping
}

POST with angular $http and Chrome's REST client gives 400 Bad request error

I am trying to make a REST call to my spring controller on jboss
#RequestMapping(value = "/myMethod", method = RequestMethod.POST)
public
#ResponseBody
String myMethod(#RequestBody MyClass myClass) {
String json = null;
String METHOD_NAME = "getAuditForRecordId";
Gson gson = new GsonBuilder().create();
try {
json = gson.toJson("success");
}
return json;
}
My angular post call
$http.post(<URL to myMethod>, postData,
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}).success(function () {
d.resolve(response);
}).error(function () {
d.reject();
}
);
is failing with a 400 Bad request error. I have a CORSFilter for my jboss app
#Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse response=(HttpServletResponse) resp;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Accept, Content-Type");
chain.doFilter(req, resp);
}
GET methods inside the same controller are working fine. But this above POST fails.
My POST JSON object has nested objects.
I also tried the same POST call from Chrome's REST client but still get the same error. Can someone point to the obvious mistake I am making here?
The error is that the url on the post is allocated in other domain, not in the same domain that are your project running, you dont call url form other domain.
This is my example:
#RequestMapping(value = "/listAll.json", params = {"page","pageSize","order","filter"}, method = RequestMethod.GET, produces={"application/json; charset=ISO-8859-1"})
#ResponseBody
public String listAll(#RequestParam("pageSize") int pageSize, #RequestParam("page") int page, #RequestParam("order") String order, #RequestParam("filter") String filters){
return this.pilmotiformService.listAllIntermediario(pageSize, page, order, filters);
}
#RequestMapping(value = "updateRecord.json", method = RequestMethod.POST, produces={"application/json; charset=ISO-8859-1"})
#ResponseBody
public String UpdateRecord(#RequestParam("cons") Long cons) throws Throwable{}
From Angular:
myApp.service('myService', function($http, $rootScope, $routeParams) {
this.oneFunction = function() {
return $http({
method: 'GET',
url: WEB_SERVER+'/oneMethod.json',
params: {modulo: 'FMT_FORMREGI,FMT_AUDITORIA,FMT_ESTADO,FMT_ADJUNTO,PIL_USUA,PIL_MOTIVO,PIL_MOTIFORM' }
});
}
this.otherFunction = function(one, two, three) {
data = {one : one, two : two, three : three};
return $http({
method: 'POST',
url: WEB_SERVER+'/otherMethod.json',
data: data
});
}
});
Jackson mapper is the component that convert or serialize the data to entitys.
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-lgpl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-lgpl</artifactId>
<version>1.9.13</version>
</dependency>
i am not sure but i think what you are missing here is the that json is in this format
{"key" : "value"}
and you are trying to do "success" so may be this is what you are missing.
I may be wrong as i have not working on gson or json a lot
I found the problem. It's in the data I am passing with my post request. I had one extra property in my passed-in nested Object. When I changed the data model on my server side to include that extra property my issue was resolved.

Resources