#Context HttpServletRequest scope in Jersey ContainerResponseFilter - multithreading

I am writing an Jersey Response filter. I am using Jersey 1.17. I want to get access to some attributes of the httpServletRequest in the filter API. The way what i am doing right now is as below. Is it safe to inject the servletRequest like in the snippet below or will this cause some kind of concurrency issues? If there are multiple requests coming in conncurrently, will the servletRequest in different requests overwrite each other? Thanks for your hlep.
public class LoggingFilter implements ContainerResponseFilter {
#Context private HttpServletRequest servletRequest;
#Override
public ContainerResponse filter(final ContainerRequest req, final ContainerResponse resp) {
String s = this.servletRequest.getAttribute("xxx");
....
}
}

Section 9.1 (latest, 5.1 previously) Concurrency of the JAX-RS specification states:
Context is speciļ¬c 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.
So, as per the specification, JAX-RS implementations (e.g. Jersey) are required to ensure that the context is safe. Keep doing what you're doing.
See also: Extract request attributes from container request of Jersey

You're safe. When you're injecting HttpServletRequest / HttpServletResponse you're not dealing with a particular instance but rather with a proxy through which you're invoking calls on a real instance stored in a ThreadLocal object. Each request is processed by a separate thread which has access to it's own HttpServletRequest / HttpServletResponse. Beside injecting HttpServletRequest / HttpServletResponse you can also inject ThreadLocal<HttpServletRequest> / ThreadLocal<HttpServletResponse> and through '#get()` method you can obtain the real request / response instances intead of proxies.

Related

Ad-Hoc type conversion in JOOQ DSL query

scenario:
we store some encrypted data in db as blob. When reading/saving it, we need to decrypt/encrypt it using an external service.
because it is actually a spring bean using an external service, we cannot use the code generator like dealing with enums.
I don't want to use dslContext.select(field1, field2.convertFrom).from(TABLE_NAME) because you need to specify every fields of the table.
It is convenient to use dslContext.selectFrom(TABLE_NAME). wonder if any way we can register the converter bean in such query to perform encrypt and decrypt on the fly.
Thanks
Edit: I ended up using a service to encrypt/decrypt the value when it is actually used. Calling an external service is relatively expensive. Sometimes the value isn't used in the request. It may not make sense to always decrypt the value when reading from db using the converter.
because it is actually a spring bean using an external service, we cannot use the code generator like dealing with enums.
Why not? Just because Spring favours dependency injection, and you currently (as of jOOQ 3.15) cannot inject anything into jOOQ Converter and Binding instances, doesn't mean you can't use other means of looking up such a service. Depending on what you have available, you could use some JNDI lookup, or other means to discover that service when needed, from within your Converter.
Another option would be to use a ConverterProvider and register your logic inside of that. That wouldn't produce your custom type inside of jOOQ records, but whenver you convert your blob to your custom data type, e.g. using reflection.
How to access Spring Beans without Dependency Injection?
If you need to access your Spring Beans you don't need Dependency Injection. Simply create the following class and you can get beans from the static method getBean():
#Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static <T> T getBean(Class<T> type) {
return applicationContext.getBean(type);
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextHolder.applicationContext = applicationContext;
}
}

How to create a CDI Interceptor which advises methods from a Feign client?

I've been trying to figure out how to intercept methods defined in a Feign client with CDI (1.2) interceptors. I need to intercept the response value the client is returning, and extract data to log and remove some data prior to it being returned to the calling process.
I'm running a Weld 2.3 container which provides CDI 1.2. In it, I would like to create a CDI interceptor which is triggered everytime a call to filter() is made.
public interface MyRepository {
#RequestLine("POST /v1/data/policy/input_data_filtered")
JsonNode filter(Body body);
}
and a matching Producer method:
#Produces
public MyRepository repositoryProducer() {
return Feign.builder()
.client(new ApacheHttpClient())
.encoder(new JacksonEncoder(mapper))
.decoder(new JacksonDecoder(mapper))
.logger(new Slf4jLogger(MyRepository.class))
.logLevel(feign.Logger.Level.FULL)
.target(MyRepository.class, "http://localhost:9999");
}
I've tried the standard CDI interceptor way by creating an #InterceptorBinding and adding it to the interface definition, but that didn't work. I suspect because the interceptor must be applied to the CDI bean(proxy) and cannot be defined in an interface. I tried applying it to the repositoryProducer() method but that too was non functional.
I've read about the javax.enterprise.inject.spi.InterceptionFactory which is availabel in CDI 2.0, but I don't have access to it.
How can I do this in CDI 1.2? Or alternatively, is there a better interceptor pattern I can use that is built into Feign somehow?
The short, somewhat incorrect answer is: you cannot. InterceptionFactory is indeed how you would do it if you could.
The longer answer is something like this:
Use java.lang.reflect.Proxy to create a proxy implementation of the MyRepository interface.
Create an InvocationHandler that performs the interception around whatever methods you want.
Target Feign at that proxy implementation.

Are jaxrs 1.1 (WLP 8.5) annotated methods thread safe?

I am using jaxrs1.1 jar shipped with Websphere liberty profile 8.5 for creating REST WebService.
Lets suppose we have a method addNewProject as shown below :
If many people call this webservice method to add project concurrently. using link below , are there any concurrency issue? In servlet, each request is a separate thread , is it the same case here or should we handle concurrency by ourselves ?
endpointLink: http://somehost.com/path1/path2/addprojectdetails and POST the JSON object.
#POST
#Path("addprojectdetails")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response addNewProject(ProjectDetails projectdetailsObj) {
return Response.status(200).entity("Project"+projectdetailsObj.getProjectname()+"successfully added").build();
}
I'm not sure what kind of concurrency issues you might be thinking of. The object itself can be either a singleton or request scoped (if using CDI) or a stateless session bean (if using EJB). If you're using a singleton, then you may need to be thread aware and not store state within the class.
It would probably help to understand what kind of concurrency issues you had in mind to answer more thoroughly.

Calling a method in a managed bean from URL Request

I'm working on Spring MVC with richfaces.
Is there a way to call a method in a managed bean Controller from URL?
e.g: website.com/somecontroller/somemethod?x=1
I tried #RequestMapping but didn't work.
Thanks in advance
When the browser client want to access to an URL, the managed beans declared in the page will be created, the constructor and #PostConstruct methods will be invoked server side.
You can recover the parameters using #ManagedProperty as proposed by BalusC (as he says, the JSF-ish way):
Parameters in URL JSF 2
If that answer doesn't fit for your needs, you can recover the request object and get the parameters one by one, as stated in the question:
HttpServletRequest request = (HttpServletRequest)FacesContext.
getCurrentInstance().getExternalContext().getRequest();
String clipId = request.getParameter("x");

JBoss AS 7, Java EE 6 how to get clients IP?

I have a simple question, but I'm searching for longer time, but I always found the same answers,which i don't really know how to handle...
i want to get the IP adress of the client, when he registers to my application...
i found something like this:
#ManagedBean(name="testController")
#SessionScoped
public class TestController implements Serializable {
private static final long serialVersionUID = -3244711761400747261L;
protected final HttpServletRequest req;
public TestController(HttpServletRequest req) {
this.req = req;
System.out.println(this.req.getRemoteAddr().toString());
}
}
but i don't have the HttpServletRequest in the constructor....
or i don't know how to use it, all i get are errors....
It's available by the ExternalContext#getRequest().
public TestController() {
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
System.out.println(request.getRemoteAddr());
}
Note that you're making one major conceptual mistake in your initial attempt. You're attempting to assign the current HTTP request as a property of a session scoped managed bean. The HTTP request instance will expire by the end of the current HTTP response and thus not be valid anymore and throw exceptions in all colors when you try to access its methods in the subsequent requests following the initial request when the session scoped bean was been created.
I'd go for a different approach, also used in the Seam Solder project: Make a servlet filter that captures the servlet request and makes it available via an application scoped producer. See corresponding source code of the solder project.

Resources