How can I get the IP address of the caller in a Jersey 2.25.1 application? - jersey-2.0

I've tried the approach here without luck: As the comments in the answer there mentions the HttpServletRequest is just null.
This is my filter:
public void myFilter(ContainerRequestContext request) throws IOException
{
// I don't see a way to get the IP address from the ContainerRequestContext
}
If I try to use #Context HttpServletRequest httpServletRequest, as the answer in the other question suggests, I just get a NullPointerException.
Another similar question: How to get source address / ip from inside ContainerResponseFilter

The nullpointerexception only occured in our tests. peeskillet helped me realize that injecting HttpServletRequest won't work as long as we're using jersey-test-framework-provider-jetty for our tests (see for example https://github.com/jersey/jersey/issues/2764 or https://github.com/jersey/jersey/issues/3092). If we had used something like GrizzlyWebTestContainerFactory, then injecting the HttpServletRequest would work since we then would have a ServletDeploymentContext.
We went for this solution in our tests, i.e. just mocking the HttpServletRequest where needed.

Related

How to convert SlingHttpServletRequest to POJO

I am writing a Sling servlet extending SlingAllMethodsServlet where this servlet will receive payload as json, currently I am parsing SlingHttpServletRequest to get json from request body. Instead of doing all these things, I would like to receive the payload as model class, similar to Spring framework. Is there any way to achieve this?
I tried using Sling models, though the documentation says the SlingHttpServletRequest can be adapted I couldn't get model class from request.
For sure I am missing something but not able to figure it out even after researching for few days. Any help is highly appreciated.
#Model(adaptables=Resource.class)
public class Test{
#Inject
private String param;
}
protected void doPost(final SlingHttpServletRequest request, final SlingHttpServletResponse response)
throws ServletException, IOException {
Test test = resource.adaptTo(Test.class) // getting null

Jersey 2: filters and #Context injections

I've the following question:
ContainerRequestFilter is a singleton, but reading this:
Jaxrs-2_0 Oracle Spec
in chapter 9.2, they say:
Context is specific to a particular request but instances of certain JAX-RS components (providers and resource classes with a lifecycle other than per-request) may need to support multiple concurrent requests. When injecting an instance of one of the types listed in Section 9.2, the instance supplied MUST be capable of selecting the correct context for a particular request. Use of a thread-local proxy is a common way to achieve this.
In the chapter 9.2, the HttpServletRequest is not mentioned.
So the question is: is it safe in terms of concurrency to inject the HttpServletRequest inside a custom ContainRequestFilter?
I mean this:
#Provider
#PreMatching
public class AuthenticationFilter implements ContainerRequestFilter {
#Context private HttpServletRequest request;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// This is safe because every thread call the method with its requestContext
String path = requestContext.getUriInfo().getPath(true);
// Is this safe? The property request is injected by using #Context annotation (see above)
String toReturn = (String)request.getAttribute(name);
[...]
}
I did some empirical tests on my IDE in debug mode, sending with two different browsers two different and concurrent requests and it seems to work well; I noticed that the filter's instance is ever the same (it's a singleton), but the injected HttpServletRequest is different in the two cases.
I readed even this thread: How to access wicket session from Jersey-2 request filter? and it seems that my tests are confirmed.
But I still have doubts.
Confirm?
Yes it's safe. To understand the problem, you should understand how scopes work. In any framework that deals with scopes (and injection), the feature is implemented similarly. If an object is in a singleton scope and another object in a lesser scope needs to be injected, usually a proxy of the object will be injected instead. When a call is made on the object, it's actually a call on the proxy.
Though the spec may not mention the HttpServletRequest specifically, most JAX-RS implementation have support for this. With Jersey in particular, if this was not possible (meaning the object is not proxiable), then you would get an error message on startup with something like "not within a request scope". The reason is that the ContainerRequestFilter is created on app startup, and all the injections are handled at that time also. If the HttpServletRequest was not proxiable, it would fail to inject because on startup, there is no request scope context.
To confirm that it is not the actual HttpServletRequest and is a proxy, you can log the request.getClass(), and you will see that it is indeed a proxy.
If you are unfamiliar with this pattern, you can see this answer for an idea of how it works.
See Also:
Injecting Request Scoped Objects into Singleton Scoped Object with HK2 and Jersey

How to make #EJB injection work on the server?

Looking at this answer, it says:
If you don't want to use an Application Client Container and instead just run the application client class through a java command, injection won't be possible and you'll have to perform a JNDI lookup.
However, given that I am trying to inject a DAO bean like the example shown here, if I cannot do the automatic injecting, it means my application must manually do the JNDI lookup and all the transaction begin/end that I would get for free if the #EJB actually worked.
However, since everything is all within the same Eclipse EJB Project (it also failed with the same null handle when I had my client code in a Dynamic Web Project), surely there must be an easy way to get it all working? Can anyone suggest what I am doing wrong?
Finally, this article suggests that DAOs are not needed, but if I replace within my EJB:
#EJB MyDao dao;
with the more direct:
#PersistenceContext private EntityManager em;
I still get the similar null value; is this the same injection failure problem?
NB: I have just noticed this answer:
This is a bug in Glassfish (apparently in the web services stack).
I am running v4.0 Build 89, which still has this bug? Does this mean I have to do all JPA actions the long-winded way?
I eventually found out that the problem/issue is that in order to use injection of the #PersistenceContext the class MUST be a bean itself. This is hinted at in the example on Wikipedia:
#Stateless
public class CustomerService {
#PersistenceContext
private EntityManager entityManager;
public void addCustomer(Customer customer) {
entityManager.persist(customer);
}
}
I could delete this question, but perhaps leaving this answer might provide a hint to someone, or at least show them a minimal working example of EJB and JPA.

EJB: what's the point of class-level annotations?

I'm reading this book, Pro JPA2: Mastering the Java Persistance API, and I'm not getting the usefulness of the class-level annotation like in this example:
#EJB(name="cart", beanInterface=ShoppingCart.class)
public class ShoppingCartServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession(true);
ShoppingCart cart = (ShoppingCart) session.getAttribute("cart");
//......
}
}
What's the point of putting that #EJB if the value of the cart variable won't be auto-injected in there and you have to init the var. yourself? Won't the code work just as well w/o that annotation? What does the annotation actually do?
I get the usefulness of the other type of annotations, like when you put it on the method or a variable, it'll auto-inject stuff. Just here, at the class level, it looks useless.
class level #EJB (or #Resource) defines that your ShoppingCartServlet depends on some EJB, in your case "cart". You need that, if you want to access to EJBs from non-managed context, like POJOs. In this case, you have to make a JNDI look-up in order to get a reference to the EJB which you can define either with ejb-ref (ejb-local-ref) descriptor, or class level #EJB annotation.
That looks like a class level annotation rather than method level, and I have no idea why one would want to annotate a servlet as EJB, but the #EJB annotation when used properly will provide that class with many different things for free, such as transactions etc...

Java Jersey: Get client IP in rest method on Tomcat

I have a Jersey rest webservice that runs on tomcat 6. I have a #Post method that consumes Multipart:
#Path("identify")
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_XML)
public String identifyReception(com.sun.jersey.multipart.MultiPart multiPart) throws Exception {
I would like to get the client IP address inside this method. I found out that you can use #Context HttpServletRequest inside Get method. But in post method I need the multipart input argument. I have also found out that tomcat does not support Servlet specification...
Is there another way I can do it?
I found out that you can use #Context HttpServletRequest inside Get method. But in post method I need the multipart input argument.
I don't think the two are mutually exclusive. Let your method take two arguments (I don't think it matters what order they're in) and annotate one of them with #Context. I believe that will work whether it's a get, post, whatever. You could also just annotate a field with #Context and Jersey will initialize it for you before it calls your #GET method.