I have a controller class with #ResponseBody annotation to server ajax request.
My requirement is to redirect to a servlet(post method) if a check fails. If check does not fails then i need to respond back with Json data
Class Controller {
#ResponseBody redirectTest() {
if(true) {
//send json data
} else {
//Redirect to a servlet
}
}
Is there a possible way to redirect to post method of servlet.
Is there any way to initialize the servlet on need basic, without creating any servlet mapping in web.xml.
Is there a possible way to redirect to post method of servlet.
Use the forward prefix
#ResponseBody
public String redirectTest(HttpServletRequest request) {
if (true) {
//send json data
} else {
request.setAttribute("someObj", someObj);
return "forward:/someServlet";
}
}
Is there any way to initialize the servlet on need basic, without creating any servlet mapping in web.xml.
For Servlet 3.0 or above, use the #WebServlet annotation
Related
With the micro-service architecture I have written a generic POST request handler which is consumed by all the micro-services. The post mapping in spring look like this:
#RestController
#RequestMapping(value = "/v1/", consumes = {MediaType.APPLICATION_JSON_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE})
public class V1Controller {
#PostMapping(path = "/**")
public #ResponseBody Json post () {}
}
Now while I am consuming the metrics for this endpoint using micrometer I am only getting /v1/ as the endpoint in the metrics while I am sending the full URL like /v1/demo/foo from the calling service. I tried lot of the combination but it is not working. I have also added the WebMvcTagsProvider where I am listing to request and resolving the POST api calls.
#Bean
#SuppressWarnings("unchecked")
public WebMvcTagsProvider webMvcTagsProvider(ObjectMapper objectMapper) {
return new DefaultWebMvcTagsProvider() {
public Iterable<Tag> getTags(HttpServletRequest request, HttpServletResponse response, Object handler, Throwable exception) {
if ("POST".equals(request.getMethod())) {
Tag uriTag = Tag.of("uri", String.valueOf(request.getRequestURI()));
return Tags.of(WebMvcTags.method(request), uriTag, WebMvcTags.exception(exception), WebMvcTags.status(response));
}
return Tags.of(WebMvcTags.method(request), WebMvcTags.uri(request, response), WebMvcTags.exception(exception), WebMvcTags.status(response));
}
};
}
Still it is resolving to /v1/ URL in the metrics. I tried googling alot but didn't find any solution. Thanks in advance.
The build in Spring Boot RequestMapping based metrics match on the annotations and add those as tags.
This is to avoid a tag explosion. Imagine a #RequestMapping for a path like user/{userId}, you would want to group all those calls together (user/1, user/2, user/3).
You'll want to create your own Timer in your post method that set that url tags, etc there.
If you decide to reuse the same metric name as the built in Spring Boot metric, you'll want to disable that one as well, so you don't double count those requests.
I have Mapping URL of the for "/" and a controller
#RequestMapping(value = {"/index","/"})
public ModelAndView displaySlideShow() {
return new ModelAndView("index");
}
But because of this mapping requests like /... or /? or /.dfdhj also serves the homepage. I read it that Spring tries to match the best available url.
Is there a way to prevent such mapping ?
For below URL's I receive a 404 error, this is fine since the URL's do not exist. Is it possible to create these servlets while the server is running before the error page is returned ?
http://127.0.0.1:8888/test1
http://127.0.0.1:8888/test1/test2
I'm thinking perhaps to create a generic controller that intercepts all urls if the current servlet does not exist, then create it ?
Assuming that by Spring you mean Spring MVC, you could do something like this:
#Controller
public class YourController {
#RequestMapping("/mappingA")
public void methodA() {
// (...)
}
#RequestMapping("/mappingB")
public void methodB() {
// (...)
}
// Catches all non-matched requests.
#RequestMapping("/*")
public void fake404(HttpServletRequest request) {
var uri = request.getRequestURI();
// (...)
}
}
Here is my question
I want to intercept request before any spring controller call, check and modify request URI. After that it has to call another SPRING controller method.
I used mvc:interceptors however I want to configure it with annotations thats why I need a solution for #Aspect. Everything is working but controller called twice, for the original request and for the new request. Using interceptors I return false and it cancels it, how do I do about Aspect classes? Thank you
Here is my code:
#Component
#Aspect
public class TestAspect {
#Before("execution(* mycontroller.*(..)) &&" + "args(request,response)")
public void interceptUrl(HttpServletRequest request, HttpServletResponse response) {
System.out.println("#Aspect is running!");
System.out.println(request.getRequestURI());
if (request.getAttribute("client") == null) {
request.setAttribute("client", "test");
request.getRequestDispatcher("/newpath/contact").forward(request, response);
}
}
}
You should consider #Around advice instead of #Before. In this case you can simply not execute original request chain.
I just noticed a weird problem as I've been testing my application. I was accidentally POSTing to a method that accepts HTTP GET (It was a typo - I'm a little tired), but the weird thing is that Spring was executing a GET action anyway - it wasn't throwing an error.
Here is the mapping for my GET action that I was POSTing to instead:
#RequestMapping(value = "/partialMapping/{partialMappingId}/edit", method = RequestMethod.GET)
public ModelAndView edit(#PathVariable long partialMappingId) {
return new ModelAndView(view("edit"), "partialMapping",
partialMappingService.findPartialMapping(partialMappingId));
}
What I would have expected was for Spring to say, "There is no action called /partialMapping/{partialMappingId}/edit for HTTP POST".
Instead... if you use the HandlerAdapter and pass it "POST" and "/partialMapping/1/edit", it runs my index action instead ("/partialMapping"). It doesn't throw an error. Why?
Is this a bug in spring, or is this desired behaviour? It's not a big deal when it comes to production code, but it surely makes debugging problems harder.
Here is the code I am using to execute a controller action in my tests:
protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response) {
try {
final HandlerMapping handlerMapping = applicationContext.getBean(HandlerMapping.class);
final HandlerExecutionChain handler = handlerMapping.getHandler(request);
assertNotNull("No handler found for request, check you request mapping", handler);
final Object controller = handler.getHandler();
// if you want to override any injected attributes do it here
final HandlerInterceptor[] interceptors =
handlerMapping.getHandler(request).getInterceptors();
for (HandlerInterceptor interceptor : interceptors) {
final boolean carryOn = interceptor.preHandle(request, response, controller);
if (!carryOn) {
return null;
}
}
return handlerAdapter.handle(request, response, controller);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
I found this code per another answer to a question on this site.
I believe your test code mimics the dispatch step that tries to find a matching Controller method signature after the URL and HTTP method have resolved. In other words, you are not testing your controller at the right level if you want to test the HTTP message bindings. For that kind of testing you would probably want to deploy to a server (perhaps embedded Jetty inside your test) and use RestTemplate to call it. That's what I do anyway.
If you annotate with Spring MVC annotations as below
#RequestMapping(method = RequestMethod.GET it should work.