Spring MVC and Prototype JavaScript - spring-mvc

I am trying to call a Spring MVC controller through an ajax call from JavaScript method.The javascript method is using Prototype library to make the ajax call.The controller throws JSP as output.
I am able to hit the controller as i can see in the log messages however the response seems to get lost.What could be the issue.Here is the code....
function submitNewAjxCall() {
alert('test');
new Ajax.Request('SimpleApp/home.htm',
{
method:'post',
parameters: $('formId').serialize(true),
onComplete: showresult
});
}
function showresult(resultdata) {
alert(resultdata.responseText); ****//this method is not called.....****
}
home.htm point to this controller
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
System.out.println("HomeController : " + ++i);
return new ModelAndView("home");
} --- this throws home.jsp
Thanks for your help.

Check with Firebug (Net tab) if you get the Ajax response and and see what its content is.
Maybe it makes sense to not return the whole HTML page but a JavaScript specific JSON object that's telling something about what the controller just did. Maybe add a ajax GET property to your controller where you just output plain JSON to the Response Body instead of returning the ModelAndView. Try to use onSucess in Prototype. Maybe that might work then
function submitNewAjxCall()
{
new Ajax.Request('SimpleApp/home.htm?ajax=true',
{
method: 'post',
parameters: $('formId').serialize(true),
onComplete: function(transport)
{
alert(transport.responseText);
}
});
}
Edit: To write JSON directly (e.g. using Flexjson as the serializer) you can use this in your (annotated) Spring controller:
#RequestMapping(value = "/dosomething.do", method = RequestMethod.GET, params = "ajax=true")
public void getByName(
#RequestParam(value = "name", required = true) String name,
HttpServletResponse response
)
{
response.setContentType("application/json");
try
{
OutputStreamWriter os = new OutputStreamWriter(response.getOutputStream());
List<DomainObjects> result = this.domainObjectService.getByName(name);
String data = new JSONSerializer().serialize(result);
os.write(data);
os.flush();
os.close();
} catch (IOException e)
{
log.fatal(e);
}
}

Related

ModelandView doesnt work

I created registration Controller. Everything works fine, user is create in database but then end service program doesnt go to successRegister view. I dont know why. If I return like String successRegister everything is ok.
#RequestMapping(value = "/add", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public ModelAndView registerUserAccount(#RequestBody #Valid User accountDto,
BindingResult result, WebRequest request, Errors errors) {
if (result.hasErrors()) {
return new ModelAndView("successRegister", "User", accountDto);
}
User registered = userService.register(accountDto);
if (registered == null) {
result.rejectValue("email", "message.regError");
}
try {
String appUrl = request.getContextPath();
eventPublisher.publishEvent(new OnRegistrationCompleteEvent
(registered, request.getLocale(), appUrl));
} catch (Exception me) {
return new ModelAndView("successRegister", "User", accountDto);
}
return new ModelAndView("successRegister");
}
Problem was with AJAX. I changed location after success and then ModelAndView was not return.
Your problem is with this
produces = MediaType.APPLICATION_JSON_VALUE
You says produces a JSON response but thats not true, you want to return a ModelAndView, so try to remove that attribute

How to make unit test multipart with a PUT request using Spring MVC and Spock?

I have a controller like this one:
#RestController
#RequestMapping('/v1/document')
class DocumentV1Controller {
#PutMapping
HttpEntity<Document> newdoc(
#RequestHeader Map<String, String> headers, #RequestParam('document') MultipartFile multipartFile) {
}
}
And I wan to test it using Spring MVC Test and Spock but I just can't figured out how to build a MockMultipartHttpServletRequestBuilder changing the HttpMethod from POST to PUT request.
This is the Spock specification:
class DocumentV1ControllerSpec extends BaseControllerSpec {
Should 'test and document good request on /v1/document endpoint'() {
given:
File file = new File('./src/test/resources/demoC.csv')
MockMultipartFile multipartFile = new MockMultipartFile('file',file.getBytes())
when:
ResultActions result = mockMvc.perform(fileUpload('/v1/document')
.file(multipartFile))
then:
result.andExpect(status().isCreated())
}
}
The error I get is this:
java.lang.AssertionError: Status expected:<201> but was:<405>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89)
at org.springframework.test.web.servlet.result.StatusResultMatchers$10.match(StatusResultMatchers.java:664)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171)
at gus.rest.api.v1.DocumentV1ControllerSpec.test and document good request on /v1/document endpoint(DocumentV1ControllerSpec.groovy:61)
What can I do to make it work?
I am not an expert in spock, however method fileUpload is deprecated now for Spring (at version 5.*).
There is a way to change default POST method for MockMultipartHttpServletRequestBuilder to PUT:
class DocumentV1ControllerSpec extends BaseControllerSpec {
Should 'test and document good request on /v1/document endpoint'() {
given:
File file = new File('./src/test/resources/demoC.csv')
MockMultipartFile multipartFile = new MockMultipartFile('file', file.getBytes())
MockMultipartHttpServletRequestBuilder multipart = (MockMultipartHttpServletRequestBuilder) multipart('/v1/document').with(request -> {
request.setMethod(HttpMethod.PUT);
return request;
});
when:
ResultActions result = mockMvc.perform(multipart
.file(multipartFile))
then:
result.andExpect(status().isCreated())
}
}
The trick is to use with(RequestPostProcessor postProcessor) to modify request and set method PUT to it.

HTTP Status 405 - Request method 'POST' not supported - jQuery.post()

Update: See here for solution
Using Spring MVC 4.
Here's my JavaScript code that makes the POST request:
$("input.toggleCourse").change(function(e){
var d = {
classID: classID,
courseID: courseID
};
$.post(
"<c:url value="/class/addCourse" />",
JSON.stringify(d))
.done(function(data){
alert("ok");
});
});
(Tried with and without JSON.stringify, tried full $.ajax instead of $.post)
Here's my controller
#RequestMapping(value = "/class/addCourse", method = RequestMethod.POST)
public #ResponseBody String addCourse(#RequestBody final CourseInClass cic) {
StringBuilder sb = new StringBuilder();
try{
Class c = classServ.findOne(cic.ClassID);
c.Courses.add(courseServ.findOne(cic.CourseID));
sb.append("{success:true}");
} catch (Exception e){
sb.append("{error:\"").append(e.getMessage()).append("\"}");
}
return sb.toString();
}
I checked the network log that it sends the correct headers to the correct url. Post requests work for normal forms, but not for this ajax call.
Thanks.
How do you think (String classID, String courseID) will be detected by Spring. i.e. how will the json object be mapped to java object.
If you want to use auto binding you can use jackson-mapper-asl. Take a look at this page
If you don't want to use it you can use #PathVariable,
change method signatures to public #ResponseBody String addCourse(#PathVariable String classID, #PathVariable String courseID) {..}
and then hit http://localhost:8080/<appname>/class/addCourse/<classID>/<courseID>

ASP.NET Web API Exception filter - A way to get request url from HttpRequestBase?

I've implemented a custom exception filter to my Web API. It is working as intended, except for one small detail...
In the following code sample, SaveToErrorLog saves exception details and tries to get the request url from context.Request.RawUrl. But context.Request does not contain the url that the API tried to serve when the exception happened. Is there a way to get the url when using an exception filter like this?
public class APIExceptionFilter : ExceptionFilterAttribute
{
private HttpContextBase context;
public APIExceptionFilter()
{
context = new HttpContextWrapper(HttpContext.Current);
}
public override void OnException(HttpActionExecutedContext actionContext)
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
if (actionContext != null && context != null)
{
facade.SaveToErrorLog(actionContext.Exception, context.Request);
}
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(actionContext.Exception.Message),
ReasonPhrase = "APIException"
});
}
}
As per the comment above by #emre_nevayeshirazi, you need to use the HttpActionExecutedContext. This gives you access to the request and then the required Uri.
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
var requestedUri = actionExecutedContext.Request.RequestUri;
//Do something
}

Trapping the error message inside jquery ajax - from asp.net mvc action

I was able to get the actual error message before when I was using jquery ajax+ asp.net web services. However, the same code inside jquery $ajax error no longer works.
Inside my .js I have
$.ajax({
contentType: 'application/json, charset=utf-8',
type: "POST",
url: "/Controller/DoSomething",
data: JSON.stringify({ varname: varvalue }),
cache: false,
dataType: "json",
success: function (wo) {
alert('yay!');
},
error: function (xhr) {
alert('error');
if (xhr.responseText) {
var err = JSON.parse(xhr.responseText);
if (err) {
alert(err.Message);
}
else {
alert("Unknown server error, please try again!");
}
}
}
});
Inside my Controller I have
public JsonResult DoSomething(string folderno)
{
CustomObject obj;
//get the obj value from repository here
throw new Exception("my test error message");
return Json(obj);
}
I looked at the Firebug and it appears that I am getting
"JSON.parse: unexpected character" error.
What I am trying to do here is to fake a situation when getting obj from repository throws an exception. Obviously, return Json(obj) never gets reached.
My question is, how do I deal with this situation and trap the error messages on the JS side? Do I need to do something in my controller?
In my earlier set up of Jquery+asp.net web services, I could throw an exception inside my web service method (as shown in my action now) and it would be trapped in my ajax error and the error message would be parsed out.
Now, it would appear that I need to catch the exception and pack in myself....question is how? And do I need to do this inside every action? This seems like a lot of work.
One thing I do is create a generic return object for AJAX calls.
Something like:
public class AJAXReturn
{
public string Message { get; set; }
public object Result { get; set; }
}
Then in your return functions wrap them in Exceptions (or create a generic exception handler) that will look something like:
public JsonResult DoSomething(string folderno)
{
CustomObject obj = new { FolderNo = folderno };
AJAXReturn result;
try
{
result.Message = "OK";
result.Result = obj;
}
catch (Exception ex)
{
result.Message = "ERROR";
result.Result = ex;
}
finally
{
return Json(result);
}
}
Edit: On the javascript side, just check your result for data.Message == 'OK'. If it isn't ok you can display either the specific exception info or anything you want.
Edit 2: Sorry I should've mentioned this will always return in the success callback so make sure you parse it there.

Resources