Sending data from AngularJS factory to a Spring Controller - ajax

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'
}

Related

Return error from spring controller via ajax call

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");
}
}

Tomcat Show HTTP Status 400 Error Page During Validation

I'm learning to make Bean Validation works in Spring MVC with Thymeleaf as default view. Every valid data can be saved properly. But when I tried an invalid data passed, Tomcat just showed HTTP Status 400 Error page. In Tomcat console showed something like validation but just became logging text in Tomcat console. Here is the controller that saves data (item).
#Controller
#RequestMapping("/item")
#SessionAttributes("item")
public class ItemController {
#Autowired
private ItemService itemService;
#Autowired
private ColorService colorService;
#ModelAttribute("allColors")
public List<Color> populateColors() {
return colorService.findAll();
}
#ModelAttribute("allItems")
public List<Item> populateItems() {
return itemService.findAll();
}
#RequestMapping(value = {"/image/{id}", "image/{id}"})
#ResponseBody
public byte[] showImage(#PathVariable("id") String id) {
return itemService.getItem(id).getImage();
}
#RequestMapping(value = {"", "/"}, method = RequestMethod.GET)
public String showAllItems() {
return "itemList";
}
#RequestMapping(value = {"add", "/add"}, method = RequestMethod.GET)
public String showItemAddForm(Model model) {
model.addAttribute("item", new Item());
return "itemAddForm";
}
#RequestMapping(value = {"add", "/add"}, method = RequestMethod.POST)
public String processAddItem(
#ModelAttribute("item") #Valid Item item,
RedirectAttributes model,
BindingResult errors,
SessionStatus session) {
if (errors.hasErrors()) {
return "itemAddForm";
}
itemService.saveItem(item);
session.setComplete();
model.addFlashAttribute("message", "Item has been added");
return "redirect:/item";
}
}
Is any wrong with the controller? How should I to make Bean Validation works with Spring and Thymeleaf?

Sending ajax response to another controller using Spring MVC

I have a view from where I am sending a request to a Controller and as a result getting response back to the view page. Now I want to pass the ajax response in to the next Controller but I do not know what will be the type of response in Controller
This is my ajax code:
$.ajax({
type: "POST",
url: "<c:url value="/menu/menucheckout/${restaurant_menu.name}"/>",
data : {"amount":amount, "orderoption" :orderoption, "date":date , "time":time ,'menuitemsArray': menuitemsArray ,'menuPriceArray': menuPriceArray , 'menuSpiceeArray': menuSpiceeArray , 'ItemQuantityArray': ItemQuantityArray },
success: function(response){
console.log(response);
window.location.href = "/BistroServicesMenuApp/welcome/getordercheckout/"+response.model;
}
});
Here is the Menu Controller
#Controller
#RequestMapping(value = "/menu")
public class MenuController {
#Autowired
private MenuTypeService menutypeService;
#RequestMapping(value="/menucheckout/{restaurantname}" ,method = RequestMethod.POST )
#ResponseBody
public ModelAndView menucheckout(#PathVariable("restaurantname") String restaurantname , HttpSession session, HttpServletRequest request, HttpServletResponse response) throws SQLException, NamingException, IOException
{
ModelAndView model = new ModelAndView("/welcome/getordercheckout");
System.out.println("COMING IN menucheckout CONTROLLER" + restaurantname);
System.out.println("orderoption" + request.getParameter("orderoption"));
String amount = request.getParameter("amount");
String orderoption = request.getParameter("orderoption");
String date = request.getParameter("date");
String time = request.getParameter("time");
String[] menuitemsArray = request.getParameterValues("menuitemsArray[]");
String[] menuPriceArray = request.getParameterValues("menuPriceArray[]");
String[] menuSpiceeArray = request.getParameterValues("menuSpiceeArray[]");
String[] ItemQuantityArray = request.getParameterValues("ItemQuantityArray[]");
model.addObject("restaurantname", restaurantname);
model.addObject("amount", amount);
model.addObject("orderoption", orderoption);
model.addObject("date", date);
model.addObject("time", time);
model.addObject("menuitemsArray", menuitemsArray);
model.addObject("menuPriceArray", menuPriceArray);
model.addObject("menuSpiceeArray", menuSpiceeArray);
model.addObject("ItemQuantityArray", ItemQuantityArray);
return model;
}
}
Now Here is the Second Controller "OrderController":
#Controller
#RequestMapping("/welcome")
public class OrderController {
#Autowired
private OrderService orderService;
#RequestMapping("/getordercheckout/{response}")
public ModelAndView getOrderCheckOut(#PathVariable("response") ModelAndView response)
{
ModelAndView model = new ModelAndView("/getordercheckout");
model.addObject("response" , response);
System.out.println("Response : " +response);
return model;
}
Now here I want to get the response but I am not sure what will be the datatype of reponse.
The System.out.println prints this error:
ModelAndView: reference to view with name '[object Object]'; model is null
Please Help me out as I am new to the Spring MVC.
Thank You in advance.

#ResourceMapping that accepts JSON from Ajax request

I'm searching how I can interprete a JSON parameter in my #ResourceMapping in Spring Portlet MVC. When I add #RequestBody, I got the message: #RequestBody is not supported... Really stuck on this one.
I have this:
View side:
<portlet:resourceURL var="getTest" id="ajaxTest" ></portlet:resourceURL>
<p>
<button onClick="executeAjaxTest();">Klik mij!</button>
<button onClick="$('#ajaxResponse').html('');">Klik mij!</button>
</p>
<p>
<h3>Hieronder het antwoord:</h3>
<h4 id="ajaxResponse"></h4>
</p>
<script>
function executeAjaxTest() {
var jsonObj = {
user: "Korneel",
password: "testpassword",
type: {
testParam: "test",
}
}
console.debug(JSON.stringify(jsonObj));
$.ajax({
dataType: "json",
contentType:"application/json",
mimeType: 'application/json',
url:"<%=getTest%>",
data:JSON.stringify(jsonObj),
success : function(data) {
$("#ajaxResponse").html(data['testString']);
}
});
}
</script>
Controller side:
#ResourceMapping(value="ajaxTest")
#ResponseBody
public void ajaxTestMethod(ResourceRequest request, ResourceResponse response) throws IOException, ParseException {
LOGGER.debug("ajax method");
JSONObject json = JSONFactoryUtil.createJSONObject();
json.put("testString", "Ik ben succesvol verstuurd geweest!");
response.getWriter().write(json.toString());
}
How can I use the spring magic to auto map this JSON data to my own model?
Note: It's Spring Portlet MVC, not regular Spring MVC..
#ResponseBody annotation is not supported out of the box in Spring MVC portlet framework, but you can implement #ResponseBody handling yourself.
We do it by implementing custom view type and model and view resolver.
Implement custom model and view resolver (ModelAndViewResolver), let's say JsonModelAndViewResolver.
In resolveModelAndView method, check whether controller method has #ResponseBody annotation (or more specific condition to identify JSON output - e.g. annotation + required supported mime type).
If yes, return your custom View implementation - let's say SingleObjectJson view (extending AbstractView).
Pass your to-be-serialized object to the view instance.
The view will serialize the object to JSON format and write it to the response (by using Jackson, Gson or other framework in renderMergedOutputModel method).
Register the new resolver as AnnotationMethodHandlerAdapter.customModelAndViewResolvers.
You need to build your json object like this:
var jsonObj = {
user: "Korneel",
password: "testpassword",
"type.testParam" : "test"
};
$.ajax({
dataType: "json",
contentType:"application/json",
mimeType: 'application/json',
url:"<%=getTest%>",
data:jsonObj,
success : function(data) {
$("#ajaxResponse").html(data['testString']);
}
});
In your Controller you should use the #ModelAttribute annotation:
#ModelAttribute(value = "jsonObj")
public JsonObjCommand obtenerJsonObjCommand() {
JsonObjCommand jsonObjCommand = new JsonObjCommand();
return jsonObjCommand;
}
#ResourceMapping(value = "ajaxTest")
public void ajaxTestMethod(
ResourceRequest request,
ResourceResponse response,
#ModelAttribute(value = "jsonObj") JsonObjCommand jsonObjCommand)
throws IOException, ParseException {
LOGGER.debug("USER: " + jsonObjCommand.getUser());
LOGGER.debug("Password: " + jsonObjCommand.getPassword());
LOGGER.debug("TestParam: " + jsonObjCommand.getType().getTestParam());
LOGGER.debug("ajax method");
JSONObject json = JSONFactoryUtil.createJSONObject();
json.put("testString", "Ik ben succesvol verstuurd geweest!");
response.getWriter().write(json.toString());
}
Don't forget your beans:
public class JsonObjCommand {
private String user;
private String password;
private TypeJson type;
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public TypeJson getType() {
return type;
}
public void setType(TypeJson type) {
this.type = type;
}
}
public class TypeJson {
private String testParam;
public String getTestParam() {
return testParam;
}
public void setTestParam(String testParam) {
this.testParam = testParam;
}
}
According to the documentation, #RequestBody is only supported in Servlet environments, not Portlet environments (same for #ResponseBody). So it seems you can't use that functionality.

When to use HttpServletRequest class in a Spring Mvc Controller

I am reading a book about spring and in the chapter about spring mvc the author list the following controller code that is responsible for form submission.
My question (since the author is not referring to it is why and where we should use HttpServletRequest)
Here is the method :
#RequestMapping(value = "/{id}", params = "form", method = RequestMethod.POST)
public String update(#Valid Contact contact, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest, RedirectAttributes redirectAttributes, Locale locale)
{
logger.info("Updating contact");
if (bindingResult.hasErrors())
{
uiModel.addAttribute("message", new Message("error", messageSource.getMessage("contact_save_fail", new Object[]{}, locale)));
uiModel.addAttribute("contact", contact);
return "contacts/update";
}
uiModel.asMap().clear();
redirectAttributes.addFlashAttribute("message", new Message("success", messageSource.getMessage("contact_save_success", new Object[]{}, locale)));
contactService.save(contact);
return "redirect:/contacts/" + UrlUtil.encodeUrlPathSegment(contact.getId().toString(), httpServletRequest);
}
Use it whenever you need to use it...
In this example, the author is using it get the character encoding :
return "redirect:/contacts/" + UrlUtil.encodeUrlPathSegment(contact.getId().toString(), httpServletRequest);
Here is the code from the UrlUtil class :
public class UrlUtil {
public static String encodeUrlPathSegment(String pathSegment, HttpServletRequest
httpServletRequest) {
String enc = httpServletRequest.getCharacterEncoding();
if (enc == null) {
enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
}
try {
pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
} catch (UnsupportedEncodingException uee) {
}
return pathSegment;
}
}
More information about the HttpServletRequest class :
It extends the ServletRequest interface to provide request information for HTTP servlets. You might consider reading the javadoc if you want to learn more about the methods of the class.

Resources