#Autowired HttpServletResponse - java

I'm looking for a way to autowire HttpServletResponse. It doesn't work with spring out of the box, but I've found this description. This works but is sort of annoying, in that spring obviously has a mechanism to make objects request scoped (i.e. HttpServletRequest) and this seems to be a hack bolted on top.
Is there a way to hook into the same mechanism that spring uses for HttpServletRequest? And, any idea why spring team decided to only make HttpServletRequest autowire capable (and excluded HttpServletResponse)?

Perhaps there is some workaround, but it's not that obvious, because it's not the way it's meant to be. Spring MVC is meant to have singleton #Controller beans that provide #RequestMapping methods which take the request and response as arguments.
If you need the response in another place (the service layer) - don't do it. The response should not go beyond the web (controller) layer.
To inject the response, you need:
- to store the response in a ThreadLocal
- to make a factory bean that returns the current response
About the example code you showed - I'm not sure if you are not going to need the factory bean to return a proxy (implementing HttpServletResponse), which in turn to return the current response. And it gets rather complicated.
But ultimately - you should not do that. If you need to intercept multiple controller invocations, use an mvc-interceptor. If you really need to use an aspect, you can get the response if it is passed as argument to the intercepted method.

Can you simply include the request in the method handle?
#RequestMapping(method=Method.GET, value="myUrl")
public String doGet(HttpServletResponse response){//spring will put the response in for you
...
}

Related

Producer for injecting HttpServletResponse

As I've read here and tried myself, it is not possible to inject the HttpServletResponse of the current #RequestScoped.
So it seems that you have to implement a custom CDI Procuder or #Produces method to be able to inject the HttpserlvetResponse. I have two questions:
Where would one implement this producer? Maybe with a web filter that sets the response in a #RequestScoped bean?
Is injecting the response even a good idea in the first place since there is no way to inject the response by default?
Never mind. I just found the Servlet module from Apache DeltaSpike which allows for injectable servlet objects such as the HttpServletResponse. So there is no need for a custom CDI Producer or #Produces method.

Validation of request body AND request parameter in 1 step?

a question to validation of put calls to a REST endpoint using spring boot and javax.validation (not the spring validation).
You have the following method in the resource:
#PutMapping(...)
public Response getResult(#RequestBody #Valid myBody, #PathVariable #MyIdValidation long id) {
}
When I call the method, myBody gets validated and I get a MethodArgumentNotValidException in my exception handler. But parameter id gets not validated!
Only if myBody is valid, id gets validated as well.
The only solution I found is to not use #Valid, and implement the validation of the body myself.
Are there better solutions?
TIA
Kibu
I don't think its doable by Spring MVC framework itself because framework handles #RequestBody and others like #RequestParam or #PathVariable differently by using different components. Also, both pieces need to be disconnected because you might not like to validate all arguments of a method.
#RequestBody is handled by org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor and validations are called from there & for params or path variable validations are done by org.springframework.validation.beanvalidation.MethodValidationInterceptor.
So in my opinion, method arguments of a controller method are handled one by one by framework & are disconnected in logic so these validations can't be clubbed together.
I've put some effort into this issue and started a project on github
It's possible to validate in one stop, but you need a different approach. Check out the project and test it.
Kibu

How does Spring routing work? Is there a way to access it?

I'm building a rest API in Spring. Is there a way to tap into the routing to do a lookup?
Is there a table somewhere?
Given a full route /someobject/a with an ACCEPT header of "whatever", is there a way I can tell what controller and method it will get routed to, Or do I need to build that map myself?
I asked a similar question in a different way and was suggested to use Spring AOP which I tried with #Before, but it doesn't work in some of the cases I need. Specifically, if there are validation annotations on the method parameters and the validation fails, it doesn't make it to the join point. Doesn't make it to the #AfterThrowing either.
For those trying to figure this out in the future, yes it is indeed possible. The routing is exposed as a bean:
#Autowired
private RequestMappingHandlerMapping requestMappingHandlerMapping;
You need the HttpServletRequest object which you can get from here if you don't have it already:
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
Then you just call:
HandlerMethod handlerMethod = (HandlerMethod)requestMappingHandlerMapping.getHandler(request).getHandler();
My specific need was to get the PreAuthorize attribute, but you can do anything with the HandlerMethod object:
PreAuthorize preauthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);

Spring RestController - Intercept method invocation

I have a Spring RestController with an endpoint consuming JSON. It converts the JSON to an object, and validates the fields (using bean validation):
#RequestMapping(method = RequestMethod.POST, consumes = "application/json")
public ResponseEntity<?> myMethod(#Valid #RequestBody MyEntity e) {
...
}
I'd like to intercept the invocation of this method only after the conversion and validation has taken place to have access to MyEntity and possibly abort execution.
Using Spring interceptors, I can only intercept the request before it reaches the method - so I don't have access to the validated bean. I can use Spring AOP and add a pointcut, but is there a way of aborting the execution nicely – ideally without throwing an exception?
This functionality is outside of the business logic of this method, and is temporary – so I want to separate it.
A possible solution is to create a bean proxy between the Spring's proxy object and an object of your original class. To do that you need:
Implement your own BeanPostProcessor.
Spring will call its postProcessBeforeInitialization() method right after it has instantiated an object of your class, but before wrapping and initialising it. In this method, identify which beans must be provided with your functionality. It's often done by means of your custom annotations on methods or classes.
Create your own proxy for the beans from step 2. You can use cglib or something more modern for that. Your proxy will make all the checks you need and then call the parent's method if everything is ok, or just silently return from the method if something is wrong.
Return your proxy from postProcessBeforeInitialization(), it will instruct Spring to use it instead of the original bean.
As the result, Spring will create proxy of your proxy, not of the original object. When a request arrives, Spring will do the validation and send it to your proxy. Your proxy will make all your custom checks and decide on whether to send it further to your original class or to return immediately.

Can I get the current webflow state within a Spring MVC controller?

On the surface, a bit of a strange question! but I am creating a web app that uses both webflow and traditional Spring MVC controllers.
From one of the webflow views, a http request (ajax) is made from the client to a spring controller. When this was originally coded it didnt have much of a logical connection to the webflow, but now things have moved on and the controller could really do with knowing what screen (view-state) the request has come from.
My controller method signature looks like this:
#RequestMapping(value="/AjaxStuff", method=RequestMethod.POST)
public String ajaxStuff(#ModelAttribute("quote") QB2MotorQuote p_quote, BindingResult p_bindingResult,
HttpServletRequest p_req, Model p_model, DefaultMessageContext p_messages) {
I know from some of my webflow action classes that I can get the current state from the RequestContext object:
public Event checkDeclines(RequestContext p_ctx) throws Exception {
// get the current state
StateDefinition state = p_ctx.getCurrentState();
I've never really understood the 'voodoo' :) that Spring does where it can automagically inject parameters just by specifying them on the method signature (surely it can only inject things it knows about ??). I've tried simply changing the method signature of my controller method to inject in the RequestContext (in the vain hope that it will get injected), but it doesn't. It complains that RequestContext is an interface.
So, does anyone know how I can make my controller know about the current webflow state - either through injecting something into the controller method signature, or perhaps I can get it from the http request somehow (or session, which I can get from the request).
Any help with this very much appreciated.
inside your webflow view, you should have access to a variable ${flowRequestContext} that you can use in your ajax call.
you can just get the piece of information ${flowRequestContext.currentState} you want from it and add it as a parameter.
you cannot have the requestContext directly injected as your are not in a webflow environment. If you were, you could directly use RequestContext.getRequestContext(). Try calling it from your MVC controller and you will get null. Try from within a flow and you will get it.

Categories

Resources