Return error from spring controller via ajax call - ajax

I am trying to develop a spring boot application involving sports, I can not see how to return my error after an ajax call in the error section instead of success, I wonder how I can recuperate all the returns coming from the controller of the Class error in the error section and not in the success section
N.B : Everything work fine in this code, only errors are returned in success part.
Class Error:
public class Error extends Exception{
public String code;
public String message;
}
Class Sport:
public class Sport {
public String id;
public String name;
}
Ajax Call
$.ajax({
type : "GET",
url : "/sports-actions",
data: {"id" : sportId},
contentType: "application/json",
dataType : 'json',
success: function (result) {
console.log(result);
},
error: function (e) {
console.log(e);
}
})
Spring Controller
#RestController
#RequestMapping("/sports-actions")
public class SportController {
#RequestMapping(method = RequestMethod.GET)
public Object deleteSport(#RequestParam("id") String id) {
return new Error(404, "id is not valid");
}
}
Edit
I extended my Error class from Exception, but I have error doing this
throw new Error(400 ,"id is not valid") // I get incompatibale type...

You can do following for testing purpose:
#RequestMapping(method = RequestMethod.GET)
public ResponseEntity<Object> deleteSport(#RequestParam("id") String id) {
if({if id exists}) {
return new ResponseEntity<Object>({your response object}, HttpStatus.OK);
} else {
//If the id doesn't exist.
return new ResponseEntity<Error>(new Error(),HttpStatus.BAD_REQUEST);
}
}
Best Practice
You should use #ControllerAdvice to handle exceptions using #ExceptionHandler on method level.
#ControllerAdvice
public class RestControllerAdvice {
#ExeptionHandler(NotFoundException.class)
public ResponseEntity<Error> handleNotFound(NotFoundException nfe) {
//LOG error
Error error = new Error();
error.setCode(HttpStatus.NOT_FOUND);
error.setMessage("ID not found OR Your custom message or e.getMessage()");
return new ResponseEntity<Error>(error, HttpStatus.NOT_FOUND);
}
}
Your controller method
#RequestMapping(method = RequestMethod.GET)
public ResponseEntity<Object> deleteSport(#RequestParam("id") String id) {
if({if id exists}) {
return new ResponseEntity<Object>({your response object}, HttpStatus.OK);
} else {
throw new NotFoundException("Id not found");
}
}
Above ControllerAdivce method will get invoked, if your NotFoundException is thrown during request processing. You can always customize the error.

Your current implementation of SportController will return HTTP status 200 which will never go into error: function (e) {. You need to throw an exception from the controller in order to get into error block.
#RestController
#RequestMapping("/sports-actions")
public class SportController {
#RequestMapping(method = RequestMethod.GET)
public Object deleteSport(#RequestParam("id") String id) throws Error {
throw new Error("Test exception block");
}
}

Related

Default return error for white label erorr

I have this controller which is open when user is redirected.
#Controller()
public class RedirectController {
#RequestMapping(method = RequestMethod.GET, value = "/redirect")
#ResponseBody
public String handleRedirectMessage(HttpServletRequest request) throws Exception {
......
}
}
But when the match is not found I get Whitelabel Error Page. Is there some way to set default handler which is by default open when path is not correct?
You need add following property:
server.error.whitelabel.enabled=false
And implement org.springframework.boot.web.servlet.error.ErrorController interface and overrides its getErrorPath() to return a custom path to call when an error occurred:
#Controller
public class MyErrorController implements ErrorController {
#RequestMapping("/error")
public String handleError() {
//do something like logging
return "error";
}
#Override
public String getErrorPath() {
return "/error";
}
}
After that add error page for path "/error" Thymeleaf error.html.
Also you could add pager for different errors:
#RequestMapping("/error")
public String handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
Integer statusCode = Integer.valueOf(status.toString());
if(statusCode == HttpStatus.NOT_FOUND.value()) {
return "error-404";
}
else if(statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
return "error-500";
}
}
return "error";
}
You can find here full code example
and description.

Hibernate how to return Json value?

Hi I have this controller method that returns a list of customers and displays it using a model.
#Controller
public class timesheetController
{
#Autowired
private CustomerDAO customerDAO;
#GetMapping("/getCustomers")
public String getCustomers(Model view)
{
//get customers from dao
List<Customer> results = customerDAO.getCustomers();
//add the customers to the model
view.addAttribute("customers", results);
return "list-customers";
}
}
However I would like to return the list as a json to get an output like
{
"Customer_Code": T77A,
"Customer_Name": CustomerName1
},
{
"Customer_Code": T77B,
"Customer_Name": CustomerName2
}
I tried just returning the list as follows
#Controller
public class timesheetController
{
#Autowired
private CustomerDAO customerDAO;
#GetMapping("/getCustomers")
public List<Customer> getCustomers()
{
//get customers from dao
List<Customer> results = customerDAO.getCustomers();
return results;
}
}
but then I get this error as it seems to be expecting a view. How can I return the desired json output?
well you are trying to call getCustomers.jsp. What you want, instead, is not a JSP page but a JSON response. So you should make an AJAX call (by using JQuery or other framework or native JS)
So what I would do is change your Controller class in this way:
#Controller
public class timesheetController
{
#Autowired
private CustomerDAO customerDAO;
#GetMapping("/getCustomers", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE })
public ResponseEntity<List<Customer>> getCustomers()
{
List<Customer> payload = customerDAO.getCustomers();
return ResponseEntity
.ok()
.contentType(MediaType.APPLICATION_JSON_UTF8)
.body(payload);
}
}
Then I would make the JSON call (I'm using JQuery in this example):
var baseUrl = YOUR_WEB_APP_CONTEXT/getCustomers;
$.ajax({
type: "GET",
url: baseUrl,
success: function(data) {
//All OK.. you should have the JSON response
},
error: function() {
//Something was wrong; you chould check
}
});

Throw custom exception from Spring controller and receive it in ajax-post error function

So, i need to add custom validation to my page, the problem is, i don't have any form, i collect and send data almost manually, here is my ajax post:
$.ajax({
type: "POST",
url: "/settings/propertyedit",
dataType: 'json',
contentType: 'application/json;charset=UTF-8',
data: {
propertyName : propName,
propertyValue : propVal,
Id : Id,
SettingId : SettingId,
},
beforeSend: function (xhr) {
xhr.setRequestHeader($.metaCsrfHeader, $.metaCsrfToken);
},
success: function (response) {
//Do some something good
},
error: function(response){
//do some something worning
}
});
And controller:
#Link(label = "property edit", family = "SettingsController", parent = "Settings")
#RequestMapping(value = "/settings/propertyedit", method = RequestMethod.POST)
#ResponseBody
public String atmpropertyedit(#RequestParam String propertyName,
#RequestParam String propertyValue,
#RequestParam Long Id,
#RequestParam Long SettingId) {
//Check if it is an error
//If correct i want to return some text in success function
//If error happens want to return some relevant text to error function
}
So, the point is, that validation is also custom, so i cant throw exception simply with try catch and if i am trying to do something like:
return new ResponseEntity<>(HttpStatus.NOT_EXTENDED);//Error type is for testing purposes
I will get 400 error even without triggering into my controller. At this point i just want some simple method to let know my ajax what has happened in my controller.
The controller can be as simple as this one, you can make it happen with custom response class which I named CommonResp and an Enum VALIDATION.
Controller - returns Response class.
#ResponseBody
public CommonResp atmpropertyedit(#RequestParam String propertyName,
#RequestParam String propertyValue,
#RequestParam Long Id,
#RequestParam Long SettingId) {
// error
if (!isValidPropertyName(propertyName)) return new CommonResp(VALIDATION.INVALID_PROPERTY_NAME);
// success
return new CommonResp(VALIDATION.OK);
}
}
CommonResp.java - will be the json response.
public class CommonResp implements Serializable {
private int code;
private String message;
public CommonResp() {
this(VALIDATION.OK);
}
private CommonResp(final int code, final String message){
this.code = code;
this.message = message;
}
public CommonResp(VALIDATION validation) {
this(validation.getCode(), validation.getMessage());
}
/* Getters and Setters */
}
VALIDATION.java
public enum VALIDATION {
OK(200, "OK"),
INVALID_PROPERTY_NAME(401, "PropertyName is not valid");
private int code;
private String message;
private VALIDATION(int code, String message) {
this.setCode(code);
this.message = message;
}
/* Getters and Setters */
}
Please let me know if there are any better implementations. (propably tons of, It's just that i don't know :P)

Spring - Stop redirection on error

I have a page to manage users and I would like to stay on the page if any error occurs when clicking save.
The only cases I found online where to do with validation.
Also my page requires the userId to be posted so I don't think returning the name of the original page in the controller would work. Also I would loose the changes made in the page.
What I am trying to achieve is stay in the same page, showing a message to the user.
Here is my controller:
#RequestMapping(method = RequestMethod.POST)
public String editUser(#RequestParam("userId") String userId, final Map<String, Object> model) {
User user = spiService.getUser(userId);
model.put("user", user);
configureRoles(model, user);
return "edituser";
}
#RequestMapping(path = "/updateUser", method = RequestMethod.POST)
public String updateUser(#RequestParam("userJson") String userRoles, #RequestParam("userId") String userId, final Map<String, Object> model) throws IOException {
User user = spiService.getUser(userId);
try {
addRoles(JsonUtil.getField(userRoles, "addedRoles"), user.getRoles(), userId);
removeRoles(JsonUtil.getField(userRoles, "removedRoles"), user.getRoles(), userId);
} catch (Exception ex) {
// What now?
}
return "users";
}
Instead of redirecting you can use Ajax calls in your controller. For that you have to create one AjaxPojoClass for exampleAjaxResponseBody as your convenience.
For example
$.ajax({
type : "POST",
contentType : "application/json",
url : "/yourUrl",
data : JSON.stringify(data),
dataType : 'json',
success : function(data) {
window.location.replace("/successUrl")
},
error : function(e) {
display(e);
},
});
AjaxController
#Controller
public class AjaxController {
#ResponseBody
#RequestMapping(value = "/yourUrl")
public AjaxResponseBody getSearchResultViaAjax(#RequestBody SearchCriteria search) {
AjaxResponseBody result = new AjaxResponseBody();
//logic
return result;
}
}
you can use ajax to submit your request.

Sending data from AngularJS factory to a Spring Controller

I have a spring controller which should recieve data in the sessionAttribute from an angularjs factory.
My Spring Controller is :
#Controller
#SessionAttributes("dataObject")
public class ScreenDesignerController extends BaseController {
/**
* Injected screen designer service class.
*/
#Autowired
private ScreenDesigner screendiService;
#RequestMapping(value = "FormBuilder", method = RequestMethod.POST)
public final String knowDetails(
#ModelAttribute("globalUser") User globalUser,
#RequestParam(value = "dataObject") String myJsonStr,
BindingResult result, RedirectAttributes redirectAttributes,
final Model model
) throws Exception {
try {
logger.info("this is json array: " + myJsonStr);
screendiService.addData(myJsonStr);
} catch (Exception e) {
logger.info("inside customiseForm POST catch");
}
return "ScreenDesigner/FormBuilder";
}
Angular factory:
indApp.factory('sendJsonDataService', function ($http, $rootScope, superCache) {
var sendjsondataservice = {
sendJsonData: function () {
//dataObject = JSON.stringify(superCache.get('super-cache'));
alert(JSON.stringify(dataObject));
res = $http.post('FormBuilder', dataObject);
res.success(function(data, status, headers, config) {
alert("Your Screen has been saved successfully into the database!");
});
res.error(function(data, status, headers, config) {
alert( "failure message: " + JSON.stringify({data: data}));
});
}
};
return sendjsondataservice;
});
Whenever I am invoking the factory via angularjs controller to recieve "dataObject", it says "bad request 400", Though the "dataObject" has valid json data in it.
I want my spring controller to receive this data.
Please help, stuck for two days now :(
Thanks in advance!!
If you're sending JSON as a POST payload, you should be using #RequestBody instead of #RequestParam.
Thy this i modified your controller :
#Controller
#SessionAttributes("dataObject")
public class ScreenDesignerController extends BaseController {
/**
* Injected screen designer service class.
*/
#Autowired
private ScreenDesigner screendiService;
#RequestMapping(value = "FormBuilder", method = RequestMethod.POST)
public final String knowDetails(#RequestBody String myJsonStr,#ModelAttribute("globalUser") User globalUser,
BindingResult result, RedirectAttributes redirectAttributes,
final Model model
) throws Exception {
try {
logger.info("this is json array: " + myJsonStr);
screendiService.addData(myJsonStr);
} catch (Exception e) {
logger.info("inside customiseForm POST catch");
}
return "ScreenDesigner/FormBuilder";
}
Another this be sure to send json data from AngularJS factory. For instance :
headers: {
'Content-type': 'application/json'
}

Resources