Is there any way to add cookie in method with #ResponseBody annotation? - ajax

I build my web application based on Spring MVC and come across a problem whilst trying to add a cookie in a method handling an ajax request.
I realized that method with #ResponseBody (in my example it returns a string value) does not create a "real" response and added cookies are lost.
Is there any way to add a cookie in a method called via ajax (and therefore annotated with #ResponseBody) in Spring MVC?

You can use the following signature to do this
#ResponseBody
public String x((HttpServletRequest request, HttpServletResponse response){
Cookie userCookie = new Cookie("<name>", "<valie>");
//set other cookie properties
response.addCookie(userCookie);
return "xxx";
}

Related

Spring Boot MVC - How to generate etag value of an entity programatically?

I am using Spring Boot 1.5.18 with ReactJs and I am trying to conditionally update an entity using an eTag.
I have added the following config and Spring Boot is generating the etags in the response headers.
#Bean
public Filter shallowEtagHeaderFilter() {
return new ShallowEtagHeaderFilter();
}
Now I want to check in my controller method if the etags match before updating the entity. My controller method is as follows:
#RequestMapping(method = POST, value = "/assignments/{id}/edit")
public #ResponseBody
ResponseEntity<?> editStaffAssignment(#RequestBody Resource<AssignmentDTO> dtoResource,
#PathVariable Long id,
PersistentEntityResourceAssembler resourceAssembler, Pageable pageable) {
Assignment assignment = assignHandler.updateAssignment(dtoResource.getContent(), id);
return new ResponseEntity<>(resourceAssembler.toResource(assignment), HttpStatus.OK);
}
I have included the etag header in the Axios request from the reactjs client and I can extract it in the controller method but how do I generate the current etag value on the server side programatically?
The ShallowEtagHeaderFilter calculates the ETag value based on the serialized response body, so it's not easily possible to calculate it upfront (i.e. before the response body is actually sent).
If I understand you correctly you want to employ an optimistic locking mechanism. If that's the case I'd suggest to drop the ShallowEtagHeaderFilter and instead calculate the ETag manually in the first place, like this:
String etag = calculateETag(); // TODO
return ResponseEntity.ok()
.eTag(etag)
.body(resourceAssembler.toResource(assignment));
If using JPA you could re-use the #Version field as an ETag value here.

Handle HttpSession attributes with Springboot Application

I had an old application with Java and Struts.
I do some refactoring and recode this application with SpringBoot.
But I have a problem handling the redirection between application and some external url, keeping my session attribute values.
To simplify, I have two endpoints, one in post, one in get.
First, the POST endpoint is called :
#RequestMapping(value = "/Action.do", method = RequestMethod.POST)
public String saveConfigurationPost(HttpServletRequest request){
logger.info("Set session param");
request.getSession().setAttribute("someAttribute", "value");
return "redirect:http://external-url.fr#redirectUri=internal-server/Action.do"
}
The external website do some treatment, and redirect me back to my application with a get request on the specified uri Action.do
#RequestMapping(value = "/Action.do", method = RequestMethod.GET)
public String saveConfigurationGet(HttpServletRequest request){
String myParamValue = (String) request.getSession().getAttribute("someAttribute");
logger.info("Get session param : "+myParamValue); // Return null
....
return "success"
}
But after redirect me to the GET endpoint, I always have a null value for my session attribute.
Why ?
With my old application, I used new ActionForward(forwardUrl, true) to redirect.
How could I get the same thing, simple as possible ?

how to apply post method to all request mappings in spring

How i can access to request POST data from different url-s to one controller method, for example I have /countries & /countries/{id} URL, It works very good with first one, because my code is
#RequestMapping(value = {"/{id}", "/{id}/"}, method = RequestMethod.GET)
public String getCountry(#PathVariable(value = "id", required = true) int id,ModelMap model) {
}
#RequestMapping(method = RequestMethod.POST)
public String deleteCountry(ModelMap model,HttpServletRequest request) {
}
And when I try to request POST data from second url I'm getting
HTTP Status 405 - Request method 'POST' not supported
Which is expectable because I haven't POST method with this mapping, but if I will be made one method for one mapping my code will be too ugly ant terrible, what solution I can use?
Hum why not add the "array" of value to your second method as well ?
#RequestMapping(value = {"", "/{id}"},method = RequestMethod.POST)
public String deleteCountry(ModelMap model,
HttpServletRequest request) {
Btw using POST verb to call an action that looks like it will delete the resource seems wrong, it should be a DELETE verb used
EDIT
But in reality, you should be creating 2 methods, as both those method are not supposed to do the same thing.
POST /countries should be creating country resources
POST /countries/{id} should be doing something else.
For an update prefer PUT /countries/{id}
And for a delete, prefer DELETE /countries/{id}
There is one way to have separate handler interceptors for different controllers.
Refer this link for details.
bind Spring HandlerInterceptor only to one controller
But I feel, it may be good you can create a common method to share business logic for this.
As Interceptor comes with proxy class for your controller which can be avoided unless you have complex logic.

Spring MVC REST - Block access to Web Methods

I have this method in my Controller that returns a json string to the view
#RequestMapping(value = "/getDevs", method=RequestMethod.GET)
public#ResponseBody String getDevs() throws JsonProcessingException,RemoteException,ServiceException{
ObjectMapper om = new ObjectMapper();
return om.writeValueAsString(WSCall.getDevelopers());
}
I call the method URL using ajax. Everything works fine except I can obtain the json if I put the URL directly in the browser. Is there a way to block this?
I agree with the comments above, that it is not relevant from a security standpoint, but you could probably make use of the X-Requested-With: XMLHttpRequest header that is most likely set for your AJAX requests. I can at least confirm it for jQuery, which might be on your tool stack.
So you could add the headers parameter to your #RequestMapping annotation:
#RequestMapping(value = "/getDevs", method=RequestMethod.GET, headers = { "X-Requested-With=XMLHttpRequest" })
public#ResponseBody String getDevs() throws JsonProcessingException,RemoteException,ServiceException{
[...]
}

Difference between #ModelAttribute and HttpServletRequest Attribute

I use spring mvc and I want to undestand some stuff.
At this code:
#RequestMapping(value="/enregistrerLostCard")
public #ResponseBody
void enregistrerLostCard(#ModelAttribute(value="auth") Auth auth2, HttpServletRequest request) {
Auth auth1 = (Auth) request.getAttribute("auth");
System.out.println(auth2.getLogin()); //print the right value
System.out.println(auth1.getLogin()); //i got nullpointer exception
}
#ModelAttribute(value="auth") and request.getAttribute("auth") isn't the same ?
HttpServletRequest is a Servlet container managed object. Its attribute store holds attributes that are useful in any part of the request handling by the Servlet container.
Model, ModelMap, ModelAndView, etc. are managed by Spring MVC (the DispatcherServlet stack). The attributes inside those are useful to the Spring side of the application.
In some cases, the Model attributes will be inserted into the HttpServletRequest attributes if needed. This typically happens when your handler method returns a String value as a view name. The model attributes will be pushed as HttpServletRequest attributes so that they can be used in the view, for example, in jsps.
Related:
how to pass variables from java to jsp in Spring

Resources