I have variant resources that all extend BaseResource<T>
#Component
#Path("/businesses")
public class BusinessResource extends BaseResource<Business>{
#GET
#Path({businessId}/)
public Business getBusiness(#PathParam("businessId") Integer businessId){..}
}
#Component
#Path("/clients")
public class ClientResource extends BaseResource<Client>{
#GET
#Path({clientId}/)
public Client getClient(#PathParam("clientId") Integer clientId){..}
}
I would like, that when there is a call to
/businesses/3, it will first go through a method that I will write which validates the T object and if everything is ok I will tell jersey to continue handling the resource.
Same goes for Client.
I can't use a regular servlet/filter - since it's being called BEFORE jersey servlet and I wouldn't know which resource is being called.
What is the best way to do it in Jersey?
Is there a place to interfere between knowing the method that jersey will invoke and the invokation?
There are 4 basic http methods in REST, namly GET, PUT, POST, DELETE.
Your annotation tells Jersey what method to call when a http request occurs. Jersey looks up the target URI in the request and matches it against your model. If the request is a http get it will execute the method annotiated with #Get from the class with the correct #Path annotiaton.
Usually you dont want to grant access to your resources in this annotated method directly. A common (may not perfect) way is to implement a DAO class that handles access to your resources, and of course does the validation before it returns the resource back to the #Get annotated method, which will itself only pass the resource to the client. So you will get another layer in your application between persisting (SQL, etc) and the client interface (Jersey).
You can use jersey 2.x ContainerRequestFilters with NameBinding. After having matched the resource, the bound filter will be executed prior to executing the method itself.
You can see the Jersey user guide, which states that it is possible:
Chapter 9.2.1.1 explains about PreMatching and PostMatching filters and chapter 9.4 chapter shows the execution order of jersey filters.
See my post for the implementation where I had the problem to make the filters with jersey 2 work.
Related
I'm trying to create a visualisation of REST calls among several internal and external services/servers. I'd like to know which endpoint called which other endpoint. I figured that the only way to do this is to do this on the caller side, because the receiver does not have any information about the caller endpoint.
Here's my thinking:
I create an object like RestTemplate and call the method.
I create an Interceptor or something like that, which will extract the information from the RestTemplate.
My problem is that I'm not sure how to find out which REST endpoint called the RestTemplate method. The RestTemplate (or other similar object) call could be called in nested methods, so for example the endpoint could invoke a private method, which then calls the external service itself.
Is there any way how to get this information? Or am I maybe just thinking too hard and there is an easier way to do this?
Example:
#GetMapping("/hello")
public String hello() {
methodThatCallsOtherEndpoint("something.com/weather"); // this method inside itself calls an endpoint
logRestCall("localhost:8000/hello", "something.com/weather"); // how do I do this automatically without having to type it myself?
return "hello";
}
Thanks for any help.
If these services/servers have a static IP you can possibly, tag them by their IP address?
You can use Spring Sleuth to trace the relationship between different REST calls.
I'm not sure how the interceptor works and what it is useful for. Also, why use the ClientHttpRequestInterceptor over AsyncClientHttpRequestInterceptor (or vice versa)?
In particular:
Should the intercept function be implemented on the front-end and back-end or is the back-end sufficient? How, where and when is the function called and how does data get passed to the function?
The only difference I can see between the regular interceptor and async from the docs is that in the regular you have the option to "wrap the response to filter HTTP attributes" and in async you have the option to "adapt the response to filter HTTP attributes with the help of the abstract class ListenableFutureAdapter."
So I have a Jersey REST service on a Tomcat server that takes client requests, processes them with an Entity Manager to get data from a database, then sends back a response to the client. So my question is, when is my REST class (containing the URL paths and such) created/destroyed? Is it created fresh with every new AJAX request or does it stay running and open on the server indefinitely?
Thanks!
Jersey basically runs as a single servlet that handles all of the requests. When a request is received, the URI+media types is matched (by the servlet implementation) against all the paths you have defined in your various Jersey-annotated classes. If a match is found, Jersey instantiates the relevant class and invokes the proper method and does all the appropriate magic based on annotations and return types.
The one Jersey servlet gets started once. Your Jersey-annotated class gets a new instance for each request that it handles. I usually have a bunch of #Context-annotated parameters for my constructor, so that I have all the relevant context for the request (request, URI, headers, security context, etc.) available to my API implementations.
Is it possible to have a JAX-RS web service redirect to another web page?
Like as you would do with Servlet response.sendRedirect("http://test/test.html").
The JAX-RS web service should itself redirect. I'm using RESTEasy if that's relevant.
Yes, you can do this in Jersey or any JAX-RS implementation (including RestEasy) if your return type is a Response (or HttpServletResponse)
https://eclipse-ee4j.github.io/jersey.github.io/apidocs/1.19.1/jersey/javax/ws/rs/core/Response.html
You can use either of the following:
Response.temporaryRedirect(URI)
Response.seeOther(URI)
"Temporary Redirect" returns a 307 status code while "See Other" returns 303.
For those like me looking for 302 that fall on this answer.
By looking the code of
Response.temporaryRedirect(URI)
You can customize your response code like this :
Response.status(int).location(URI).build()
Note that status code are define in enum
Response.Status
And for example 302 is Response.Status.FOUND
Extending smcg# answer above,
You can achieve this by altering the request context in a ContainerRequestFilter by using ContainerRequestContext.setRequestUri(URI). If you see the JAX-RS specification (Section 6.2) here, there is a mention of #PreMatching request filters. According to the documentation;
A ContainerRequestFilter that is annotated with #PreMatching is executed upon
receiving a client request but before a resource method is matched. Thus, this type of filter has the ability
to modify the input to the matching algorithm (see Section 3.7.2) and, consequently, alter its outcome.
A very naive filter can be like this;
#PreMatching
class RedirectFilter: ContainerRequestFilter {
override fun filter(requestContext: ContainerRequestContext?) {
requestContext!!.setRequestUri(URI.create("<redirect_uri>"))
}
}
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
...
}