Is there any way to get the request (HttpServletRequest?) programmatically? I can only find how to do it with an annotation on the endpoint method/class.
Per https://stackoverflow.com/a/5118844/190164 I can add an annotated argument to my endpoint:
#POST
#Path("/test")
#Produces(MediaType.APPLICATION_JSON)
public String showTime(
#Context HttpServletRequest httpRequest
) {
// The method body
}
Or I can injected in the class(https://stackoverflow.com/a/26181971/190164)
public class MyResource {
#Context
private HttpServletRequest httpRequest;
#GET
public Response foo() {
httpRequest.getContentType(); //or whatever else you want to do with it
}
}
however I would like access to the request in another class that isn't directly linked to Jersey. Adding the #Context injection like in the second example above doesn't work, as the class isn't instantiated by Jersey. I'd like to be able to do something like
HttpServletRequest.getCurrentRequest()
but I haven't been able to find any static method somewhere.
If you are looking for some security solutions you can use servlet filters (create class that implements Filter) or you can implement ContainerRequestFilter and by overriding filter you can perform your filtering .Outside filters The context elements are always only accessible in the controller (where you place the path annotations) , there is no way to access this type of content from outside the controller other than passing it to the method or Object desired:
#Context
private HttpServletRequest httpRequest;
#GET
public Response foo() {
someMethod(httpRequest); //or whatever else you want to do with it
}
}
hope this helps.
Related
I've developed an API using SpringBoot
but my API takes long to respond, as its a heavy application.
So I'm planning to give a response with meaningful message immediately and then run the heavy application in the back ground .
Is anyone familiar with this scenario.
I have a SpringBootWebApplication class which has main()
#SpringBootApplication
#EnableAsync
public class SpringBootWebApplication extends SpringBootServletInitializer {
}
Also have OnDemandController class
#Controller
#RequestMapping("/run/lob")
public class OnDemandControllerForLob{
#RequestMapping(value="get",method=RequestMethod.GET)
#Produces({MediaType.APPLICATION_JSON})
public #ResponseBody String processOndemandService(#Context
HttpServletRequest request, #Context HttpServletResponse response) {
//here is a method call that takes lot of time to execute
OnDemand.processtherequest();
return response
}
}
Can someone please suggest me the best way to get response immediately and run the application logic (or the method that invokes the heavy java application in the back ground). The response i need is just a string saying "your request is served".
From your post, #EnableAsync is already applied.
Now the OnDemand.processtherequest() method must be public and marked with #Asnyc.
However, OnDemand.processtherequest(); looks like a static method call (based on the name). This will not work. There must be a Spring managed bean with a non-static method. If OnDemand is not in your control then create a wrapper bean which delegates to the static method. For example:
#Service
public class OnDemandService {
#Async
public void processTheRequest() {
OnDemand.processtherequest();
}
}
And in the controller, autowire the service, and call the method. The controller method will return immediately while the method marked as #Async will run in a different thread.
#Controller
#RequestMapping("/run/lob")
public class OnDemandControllerForLob {
#Autowired
private OnDemandService onDemandService;
#RequestMapping(value="get",method=RequestMethod.GET)
#Produces({MediaType.APPLICATION_JSON})
public #ResponseBody String processOndemandService(#Context
HttpServletRequest request, #Context HttpServletResponse response) {
//here is a method call that takes lot of time to execute
// OnDemand.processtherequest();
onDemandService.processTheRequest();
return "your request is served";
}
}
I'm using the latest Spring Data Rest and I'm handling the event "before create". The requirement I have is to capture also the HTTP Headers submitted to the POST endpoint for the model "Client". However, the interface for the RepositoryEventHandler does not expose that.
#Component
#RepositoryEventHandler
public class ClientEventHandler {
#Autowired
private ClientService clientService;
#HandleBeforeCreate
public void handleClientSave(Client client) {
...
...
}
}
How can we handle events and capture the HTTP Headers? I'd like to have access to the parameter like Spring MVC that uses the #RequestHeader HttpHeaders headers.
You can simply autowire the request to a field of your EventHandler
#Component
#RepositoryEventHandler
public class ClientEventHandler {
private HttpServletRequest request;
public ClientEventHandler(HttpServletRequest request) {
this.request = request;
}
#HandleBeforeCreate
public void handleClientSave(Client client) {
System.out.println("handling events like a pro");
Enumeration<String> names = request.getHeaderNames();
while (names.hasMoreElements())
System.out.println(names.nextElement());
}
}
In the code given I used Constructor Injection, which I think is the cleanest, but Field or Setter injection should work just as well.
I actually found the solution on stackoverflow: Spring: how do I inject an HttpServletRequest into a request-scoped bean?
Oh, and I just noticed #Marc proposed this in thecomments ... but I actually tried it :)
I have a Spring boot application with resteasy-spring-3.0.19 and jboss-jaxrs-api_2.0_spec-1.0.0.
I would like to intercept all the rest calls for authorization.
The interceptor is not getting invoked. Also, How can i get the target method #Path annotation value in the interceptor.
Do I need to register this in the Spring boot app?
#Provider
public class AuthorizationtInterceptor implements ContainerRequestFilter{
/**
*
*/
public AuthorizationtInterceptor() {
// TODO Auto-generated constructor stub
}
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String method = requestContext.getMethod();
UriInfo uriInfo = requestContext.getUriInfo();
// Need the target method #Path annotation value ....
}
}
Target Rest class,
#Named
#Singleton
#Path(ROOT_PATH)
public class WebController {
#GET
#Path(TEST_PATH)
#Produces(MediaType.APPLICATION_JSON)
public Response getUser(#Context final HttpServletRequest request) {
}
}
In a post-matching filter (a filter without the #PreMatching annotation), you can use ResourceInfo to get the matched resource class and the resource method.
Inject ResourceInfo in your filter using the #Context annotation:
#Context
private ResourceInfo resourceInfo;
Then get the resource class and extract the #Path annotation:
Path path = resourceInfo.getResourceClass().getAnnotation(Path.class);
To get the resource method, use:
Path path = resourceInfo.getResourceMethod().getAnnotation(Path.class);
Depending on what you are trying to achieve, instead of comparing the value of the #Path annotation for authorization purposes, you could consider binding your filter to a set of resource classes or methods. See more details in this answer.
Depending on how you are setting up your application, you may need to register the filter in your Application subclass or in your web.xml deployment descriptor.
I have a bean being created by a service with the following class:
#Configuration
public class AccessManager {
#Bean(name="access", destroyMethod="destroy")
#Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
#Autowired
public Access create(HttpServletRequest request) {
System.out.println(request.getRemoteAddr());
return new Access();
}
}
Everything works as expected, except that when the application is starting, this method is being called, probably because I have some other singleton beans that use the Access bean. At the start up there is no request bound to the Thread, and it's expected to get a java.lang.IllegalStateException when trying to access any property of the request parameter.
No problem. The question is, is it possible to check if the underlying HttpServletRequest of the proxy request is null before calling a property that raises the exception?
You probably want to take a look at RequestContextHolder#getRequestAttributes(). That will return null if you're not currently in a context where request scope could be used.
#Configuration
public class AccessManager {
#Bean(name="access", destroyMethod="destroy")
#Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
#Autowired
public Access create(HttpServletRequest request) {
if (RequestContextHolder.getRequestAttributes() != null) {
System.out.println(request.getRemoteAddr());
}
return new Access();
}
}
I think the issue here is with separation of concerns. Usually your service layer should not have any dependency on the servlet classes. This is very much a controller/UI concern.
Your service class should be provided with the properties which it needs to do its job. In this case a String. This service method should be called from a controller method which is injected with the servlet request.
Something like the following:
#Controller
public class MyController {
#Autowired
private AccessManager accessManager;
#RequestMapping
public void handleRequest(HttpServletRequest request) {
accessManager.create(request.getRemoteAddr());
}
}
and your service would then look like this:
#Service
public class AccessManager {
public Access create(String remoteAddress) {
return new Access();
}
}
To sum up, anything annotated as #Service shouldn't have access to the Request.
I need to get the current page URL in a POJO that is being called from an Acegi class (need to add some custom logic for the app I'm working on) and need to retrieve the HttpServletRequest so that I can get the subdomain of the URL (on which the logic is based).
I've tried to add:
#Autowired
private HttpServletRequest request;
...
public void setRequest(HttpServletRequest request) {
this.request = request;
}
public HttpServletRequest getRequest() {
return request;
}
However when I try to use the request object in my code, it is null.
Any idea what I am doing wrong or how I can better go about doing this?
If the bean is request scoped you can autowire the HttpServletRequest like you are doing.
#Component
#Scope("request")
public class Foo {
#Autowired private HttpServletRequest request;
//
}
Otherwise you can get the current request as follows:
ServletRequestAttributes sra = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest req = sra.getRequest();
This uses thread-local under the covers.
If you are using Spring MVC that's all you need. If you are not using Spring MVC then you will need to register a RequestContextListener or RequestContextFilter in your web.xml.