I have a requirement that a few QueryParams should be present in absolutely all JAX-RS endpoints of my application.
Is there a way to specify somewhere, only once, these parameters? Or do I have to repeat myself in all method endpoints?
Thank you!
I would implement a ContainerRequestFilter and handle the parameters there. You can add the result to the ContainerRequestContext:
#Provider
public class MyFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
Object result = // handle the parameter
requestContext.setProperty("myParam", result);
}
}
Your implementation will of course depend on your needs.
You can inject the context into your resource classes like:
#Context
private ContainerRequestContext containerRequestContext;
See also:
Jersey 2 filter uses Container Request Context in Client Request Filter
Related
I am building a REST API with Spring Boot, and now trying to create a custom filter class where I need to access the resource method that would be invoked by the request. I need that in order to check if the method is annotated with a certain annotation, e.g.
#Component
#ApplicationScope
public class MyFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Method method = // get the target method somehow
if (method.isAnnotationPresent(MyAnnotation.class)) {
// business logic here
}
filterChain.doFilter(request, response);
}
}
With RESTEasy I would do something like this
#Context
private ResourceInfo resourceInfo;
where ResourceInfo has methods to get the resource class and method that is the target of the request. Is there a similar class in Spring Boot that would do the same job?
I making one Rest Service with Restaeasy (java) that have to return the same URL that was called but with one new string
Example Call service:
Post => mybase/myservice/somewrite with some JSON
| Reponse => mybase/myservice/somewrite/123456
So i want to make the mybase/myservice/somewrite url with one generic logic, because if i put String returnURL="mybase/myservice/somewrite"; and i change for example the name of mybase the reponse will not be good
I want somthing like this
someLogicService(JSON);
id=getId();
URL=getContextCallURL();
return URL+\/+id;
But i dont know if this is possible to do it, and less how to do it
You could also inject an instance of type UriInfo using the annotation Context within your resource, as described below:
#Context
private UriInfo uriInfo;
#POST
#Path("/")
#Consumes(MediaType.APPLICATION_JSON)
public Response makeContact(Contact contact) {
String requestUri = uriInfo.getRequestUri();
(...)
}
Hope it helps you,
Thierry
I found the answer to my problem, i put inject with #context the httpRequest to my function and call absolutPath :
#POST
#Path("/")
#Consumes(MediaType.APPLICATION_JSON)
public Response makeContact(Contact contact, #Context HttpRequest request) {
return Response.ok().header("location", request.getUri().getAbsolutePath().getPath() + contactService.makeContact(contactJSON)).build();
}
I have an #AroundInvoke REST Web Service interceptor that I would like to use for logging common data such as the class and method, the remote IP address and the response time.
Getting the class and method name is simple using the InvocationContext, and the remote IP is available via the HttpServletRequest, as long as the Rest Service being intercepted includes a #Context HttpServletRequest in its parameter list.
However some REST methods do not have a HttpServletRequest in their parameters, and I can not figure out how to get a HttpServletRequest object in these cases.
For example, the following REST web service does not have the #Context HttpServletRequest parameter
#Inject
#Default
private MemberManager memberManager;
#POST
#Path("/add")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Member add(NewMember member) throws MemberInvalidException {
return memberManager.add(member);
}
I have tried injecting it directly into my Interceptor, but (on JBoss 6.1) it is always null...
public class RestLoggedInterceptorImpl implements Serializable {
#Context
HttpServletRequest req;
#AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
logger.info(req.getRemoteAddr()); // <- this throws NPE as req is always null
...
return ic.proceed();
I would like advice of a reliable way to access the HttpServletRequest object - or even just the Http Headers ... regardless of whether a REST service includes the parameter.
After researching the Interceptor Lifecycle in the Javadoc http://docs.oracle.com/javaee/6/api/javax/interceptor/package-summary.html I don't think its possible to access any servlet context information other than that in InvocationContext (which is defined by the parameters in the underlying REST definition.) This is because the Interceptor instance has the same lifecycle as the underlying bean, and the Servlet Request #Context must be injected into a method rather than the instance. However the Interceptor containing #AroundInvoke will not deploy if there is anything other than InvocationContext in the method signature; it does not accept additional #Context parameters.
So the only answer I can come up with to allow an Interceptor to obtain the HttpServletRequest is to modify the underlying REST method definitons to include a #Context HttpServletRequest parameter (and HttpServletResponse if required).
#Inject
#Default
private MemberManager memberManager;
#POST
#Path("/add")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Member add(NewMember member, #Context HttpServletRequest request, #Context HttpServletResponse response) throws MemberInvalidException {
...
}
The interceptor can then iterate through the parameters in the InvocationContext to obtain the HttpServletRequest
#AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
HttpServletRequest req = getHttpServletRequest(ic);
...
return ic.proceed();
}
private HttpServletRequest getHttpServletRequest(InvocationContext ic) {
for (Object parameter : ic.getParameters()) {
if (parameter instanceof HttpServletRequest) {
return (HttpServletRequest) parameter;
}
}
// ... handle no HttpRequest object.. e.g. log an error, throw an Exception or whatever
Another work around to avoid creating additional parameters in every REST method is creating a super class for all REST services that use that kind of interceptors:
public abstract class RestService {
#Context
private HttpServletRequest httpRequest;
// Add here any other #Context fields & associated getters
public HttpServletRequest getHttpRequest() {
return httpRequest;
}
}
So the original REST service can extend it without alter any method signature:
public class AddService extends RestService{
#POST
#Path("/add")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Member add(NewMember member) throws MemberInvalidException {
return memberManager.add(member);
}
...
}
And finally in the interceptor to recover the httpRequest:
public class RestLoggedInterceptorImpl implements Serializable {
#AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
// Recover the context field(s) from superclass:
HttpServletRequest req = ((RestService) ctx.getTarget()).getHttpRequest();
logger.info(req.getRemoteAddr()); // <- this will work now
...
return ic.proceed();
}
...
}
I'm using Glassfish 3.1.2.2 Jersey
For http header this works for me:
#Inject
#HeaderParam("Accept")
private String acceptHeader;
To get UriInfo you can do this:
#Inject
#Context
private UriInfo uriInfo;
Hello I am using GWTP for my application development. In the application I am in need to server side session instance to put some data in that session instance. I saw some examples of GWT where there is Action class which extends ActionSupport class.
There are some method in the examples through which we can have the server side session instance.Like below :
public HttpServletRequest getRequest() {
return ServletActionContext.getRequest();
}
public HttpServletResponse getResponse() {
return ServletActionContext.getResponse();
}
public HttpSession getSession() {
HttpSession session = getRequest().getSession();
return session;
}
But I am not getting the similar thing in GWTP. Please help me out. Thanks in Advance.
Finally I got some thing which is helping me.I am sharing this here.
private Provider<HttpServletRequest> requestProvider;
private ServletContext servletContext;
#Inject
public LoginCallerActionHandler(
Provider<HttpServletRequest> requestProvider,
ServletContext servletContext) {
super();
this.requestProvider = requestProvider;
this.servletContext = servletContext;
}
Here is my action handler class.In which i can use session.
servletContext.setAttribute(SessionKeys.LOGGEDIN_USER.toString(), returnObject.getLoggedInUser());
If you are using Spring or Guice on your server side you can get Request/Response injected into your Action. For example, if your are using GWTP's DispatchServletModule, you can use features of Guice's ServletModule as:
DispatchServletModule extends Guice ServletModule and maps request
URLs to handler classes.
Here's an example from Guice wiki:
#RequestScoped
class SomeNonServletPojo {
#Inject
SomeNonServletPojo(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
...
}
}
I am not sure if GWTP binds the handlers in Singleton scope or not. If it does bind it in singleton you should inject a Provider instead.
I follow the Weld's doc
in the section 4.11. The InjectionPoint object
There is a very interesting example about how to obtain the http parameter using CDI
but i copy-pasted the code into netbeans, everything compiles, but has an deployment error
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Injection point has unsatisfied dependencies. Injection point: parameter 1 of java.lang.String com.test.HttpParamProducer.getParamValue(javax.enterprise.inject.spi.InjectionPoint,javax.servlet.ServletRequest); Qualifiers: [#javax.enterprise.inject.Default()]
how to solve this problem???
public class HttpParamProducer {
#HttpParam("")
#Produces
String getParamValue(
InjectionPoint ip, ServletRequest request) {
return request.getParameter(ip.getAnnotated().getAnnotation(HttpParam.class).value());
}
}
Every parameter on a producer method is injected, and none of your beans (including producers) provides the API type ServletRequest to satisfy this injection point.
it seems that after two years, this question is still interested
this is a short coming of the CDI spec, where it doesn't require the container to expose HttpServletRequest as injectable bean
here is a reasonable work around
#WebListener
public class HttpServletRequestProducer implements ServletRequestListener {
private final static ThreadLocal<HttpServletRequest> holder = new ThreadLocal<HttpServletRequest>();
#Override
public void requestDestroyed(ServletRequestEvent sre) {
holder.remove();
}
#Override
public void requestInitialized(ServletRequestEvent sre) {
holder.set((HttpServletRequest)sre.getServletRequest());
}
#Produces #RequestScoped HttpServletRequest get() {
return holder.get();
}
}
now #Inject HttpServletRequest will be working as expected
happy coding