#RequestMapping(params={"myyParam"}) seems to be getting ignored? - spring

I am redirecting to page using basic javascript:
window.location = "handleMyPage.ctl?myNewParameter=1234";
however when the flow of control (correctly) gets to my controller, the request is instead handled by a different (incorrect) function.
My function is annotated like:
#RequestMapping(method = { RequestMethod.GET, RequestMethod.POST }, params={"somePreExisingParameterIAmNotUsing"})
protected ModelAndView otherHandler(HttpServletRequest request, HttpServletResponse response) {
log.info("This gets called for some reason!");
}
#RequestMapping(method = { RequestMethod.GET, RequestMethod.POST }, params={"myNewParameter"})
protected ModelAndView handlerIActuallyWantCalled(HttpServletRequest request, HttpServletResponse response) {
log.info("this never gets called?");
}
I have inspected the request at the server side - and I can see the parameterMap contains only "myNewParameter" and no trace of "somePreExisingParameterIAmNotUsing" - yet still the function which references somePreExisingParameterIAmNotUsing is the only one that ever gets called.
it's worth noting, somePreExisingParameterIAmNotUsing is also the first function referenced - so I believe the request dispatcher may just be defaulting to the first function...
I know window.location= will only ever trigger GET HTTP verbs - but I'm fine with that for now - surely the method = { RequestMethod.GET, RequestMethod.POST } should cover that?
Does param not work in requestMapping when it's a GET request?

Identified the issue as I was about to hit submit.
My controller turned out to be very old: it was extending AbstractController - which is an implementation of the template method design pattern.
So Spring was looking for specific function names it expected to be implemented, and not using my annotations.
So since at some point in the code's history, someone came along and added annotations, without removing the old inherited request mapping approach - not realizing because there was only one controller function that the annotations did nothing.
Removing the extends AbstractController reference, and ensuring my controller was configured for annotations was the solution.

Related

Static website does not want to work with a simple POST endpoint

I've made a simple static website, with some CSS & JS:
If I run this with SpringBoot, everything works pretty well, even JS works.
Now, I want to add a simple POST endpoint:
#RestController
public class Generator {
#RequestMapping(name = "/generator", method = RequestMethod.POST)
public String payload(final GeneratorPayload payload) {
System.out.println("This is your payload: " + payload.getFirstName());
return "testresp";
}
}
Which throws
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported when accessing the main page (I'm not even calling that endpoint), displaying an error.
If I delete the inner mapping ("/generator"), everything works fine.
It's like he was overriding the default method and applies it to the index?
What's going on here?
There was an error here:
#RequestMapping(name = "/generator", method = RequestMethod.POST)
I've specified name, instead of value and the mapping was being attached to "/".
The correct version:
#RequestMapping(value = "/generator", method = RequestMethod.POST)

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.

How to use send.redirect() while working with Spring MVC

I was trying to redirect to a dynamic page from Interceptors and Handler Mapping program. I have already defined a controller which handles and redirects (/hello.htm) through model (I have only this controller in my program). Until this point it is working fine. Apart from this, I registered a handler which will redirect to a page once it satisfies some condition.
public class WorkingHoursInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
System.out.println("In Working Hours Interceptor-pre");
Calendar c=Calendar.getInstance();
if(c.get(Calendar.HOUR_OF_DAY)<10||c.get(Calendar.HOUR_OF_DAY)>20){
response.sendRedirect("/WEB-INF/jsp/failure.jsp");
return false;
}
return true;
..............
..............
}
But once it comes to response.sendRedirect, it is showing resource not found even though the mentioned page is present. I tried to redirect to "WEB-INF/jsp/hello.jsp" as well but keeps showing the same error. If the condition in the interceptor is not satisfied, the program works fine.
Below is shown the only controller present in the program.
#Controller
public class MyController {
#RequestMapping("/hello.htm")
public ModelAndView sayGreeting(){
String msg="Hi, Welcome to Spring MVC 3.2";
return new ModelAndView("WEB-INF/jsp/hello.jsp","message",msg);
}
}
(The controller for handling hello.html works fine if I change the interceptor condition)
Instead of redirecting, if I just print a message in the console, the program works fine. But once it comes to redirect it shows the error. Do I need to specify a separate controller to handle this request? Will this redirection request go to the dispatcher-servlet?
You need to add redirect: prefix in the view name, the code for redirect will look like:
#RequestMapping(value = "/redirect", method = RequestMethod.GET)
public String redirect() {
return "redirect:finalPage";
}
OR
#RequestMapping(value = "/redirect", method = RequestMethod.GET)
public ModelAndView redirect() {
return new ModelAndView("redirect:finalPage");
}
You may get a detail description from here:
enter link description here

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{
[...]
}

HttpServletResponse contained in servlet filter does not perform redirect

I am using Spring 4.0.6 in a servlet application. I have an abstract base controller with some general methods for all my controllers to use.
One of these methods is a redirect. I want to have a method with signature
redirect(String path)
To send a redirect, I am using
response.sendRedirect(response.encodeRedirectURL(path));
As I would like to keep method signatures short and clean, I need to get access to the response object inside the superclass method.
In order to do this, I've followed a suggestion found online, and defined a servlet filter with a ThreadLocal HttpServletResponse.
public class ResponseFilter extends OncePerRequestFilter {
private static final ThreadLocal<HttpServletResponse> responses = new ThreadLocal<HttpServletResponse>();
public static HttpServletResponse getResponse() {
return responses.get();
}
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
responses.set(response);
} finally {
try {
filterChain.doFilter(request, response);
} finally {
responses.remove();
}
}
}
}
As I am using Spring security with a Java configuration, I'm adding this filter in my WebSecurityConfigurerAdapter subclass:
.addFilterAfter(rf, SwitchUserFilter.class)
Note that I have also tried adding the filter as first in the filterchain, and that I have tried using an Interceptor instead. All with the same results.
I have compared hashcodes on the response objects, and near as I can tell, the hashcodes match, but the redirect seems to be ignored. I have also looked at object ids on breakpoints in Eclipse, and there again, I have a match. The symptom is that the spring DispatcherServlet enters processDispatchResult and seems to think it needs to resolve a view. That view does not exist, as I expect to do a redirect:
javax.servlet.ServletException: File "/WEB-INF/views/application/redirecttest.jsp" not found
I have noticed that, if I add the response object back in my requestmapping controller method signature, the superclass redirect seems to work (even though I do not use the controller method response object at all).
Unfortunately, this behavior is reproducible both on a Mac and on Linux. I use Tomcat 7 as container.
Your filter should work just fine, but the problem you're facing is another. If you are using views (as you appear to do in the example) you need to return a redirect view from your controller in order to force a redirect; just instructing the response object to redirect won't work because Spring MVC infrastructure will try to do its thing (i.e. view resolution) before the Response is returned to the Servlet container.
For instance, if you use the convention to return the view name as a String from your controller method, you need to do the following in your controller:
#RequestMapping("/redirectTest")
public String redirectTest() {
return "redirect:http://www.example.com";
}

Resources