JEE: how to pass parameter to an interceptor - java

In my JEE application, running on glassfish 3, I have the following situation:
MyFacade class
#Interceptors(SomeInterceptor.class)
public void delete(Flag somethingForTheInterceptor, String idToDelete) {
.......
}
#Interceptors(SomeInterceptor.class)
public void update(Flag somethingForTheInterceptor, MyStuff newStuff) {
.......
}
The variable somethingForTheInterceptor is not used in these methods, it is only used in the interceptor:
SomeInterceptor class
#AroundInvoke
public Object userMayAccessOutlet(InvocationContext ctx) throws Exception {
Flag flag = extractParameterOfType(Arrays.asList(ctx.getParameters()), Flag.class);
// some checks on the flag
}
Somehow it doesn't feel good to have a parameter that is not used in the method. Is there another way to "send" somethingForTheInterceptor to the interceptor?
UPDATE: The callers of delete() and update() have different ways of calculating the somethingForTheInterceptor variable. And this is not a constant. The information needed to calculate it is in the REST call. But the 2 REST methods have different input objects so it is not enough to inject the http request.
These are the callers:
MyResource class
#DELETE
#Path("/delete/{" + ID + "}")
public Response delete(#PathParam(ID) final String id) {
Flag flag = calculateFlagForInterceptor(id);
facade.delete(flag, id);
}
#POST
#Path("/update")
#Consumes(MediaType.APPLICATION_JSON + RestResourceConstants.CHARSET_UTF_8)
public Response update(final WebInputDTO updateDetails) throws ILeanException {
Flag flag = calculateFlagForInterceptor(updateDetails);
facade.update(flag, convertToMyStuff(updateDetails));
}
I was thinking - is it possible for the methods in the Resource to set the flag in some kind of Context, that can be later injected in the Interceptor?

In Java EE, Interceptors allow to add pre and post processings to a method.
So, the context of the Interceptor execution is the context of the method.
I was thinking - is it possible for the methods in the Resource to set
the flag in some kind of Context, that can be later injected in the
Interceptor?
Staless Service should be privileged when you may. So, you should avoid storing data on the server (ThreadLocal, Session, etc..).
The information needed to calculate it is
in the REST call.
Why ?
A Rest controller has no vocation to do computations and logic.
To solve your problem, are you sure you could not move the flag computation in your interceptor ?
By enhancing the interceptor responsibilities, you would have not need anly longer to transit the flag :
#AroundInvoke
public Object userMayAccessOutlet(InvocationContext ctx) throws Exception {
Flag flag = calculFlag(Arrays.asList(ctx.getParameters()));
// some checks on the flag
}

Related

is there a way to intercept the begin and end Conversation in CDI?

I would like to intercept calls to methods conversation.begin() and conversation.end().
To do this, I have developed an interceptor binding that I aim to dynamically assign to the Conversation class through a CDI portable extension.
However, I can not find how to access to the Conversation class since it is not observed in the ProcessAnnotatedType event where usually i do this process to my defined beans.
See the code as an example:
public class MethodCallsInterceptorExt implements Extension {
void processAnnotatedType(#Observes ProcessAnnotatedType<?> event) {
if (isConvesationBean(event)) { // This condition is never true
event.configureAnnotatedType().add(new MyInterceptorBinding());
}
}
}
Is this solution at least partially correct?
Is there any viable way to do this?
You could do something like this:
public class ConversationObserver {
public void onStart(#Observes #Initialized(ConversationScoped.class) ServletRequest request) {}
public void onEnd(#Observes #Destroyed(ConversationScoped.class) ServletRequest request) {}
}
See https://docs.jboss.org/cdi/api/2.0/javax/enterprise/context/ConversationScoped.html

Spring Custom Scope Lifecycle Bean Termination

Question: How can I tell Spring that a set of beans with a custom scope should all be considered garbage, so that the next request on the same thread would not re-use their state?
What I've done: I've implemented a custom scope in Spring, to mimic the lifecycle of a request scope (HttpRequest) but for TcpRequests. It is very similar what is found here.
Many examples of custom scopes which I am finding are variants on prototype or singleton with no explicit termination of beans occurring, or, alternatively, they based around a thread local or ThreadScope but they do not describe telling Spring that the lifecycle has ended and that all beans should be destroyed.
Things I have tried (perhaps incorrectly):
Event + Listener to indicate the beginning and end of the scope (these occur when message is received and just before response is sent); in listener, the scope is explicitly cleared which clears the entire map used by the thread local implementation (scope.clear()). Clearing scope does result in the next call to context.getBean() returning a new instance when handled manually in tests, but my bean which is autowired in a singleton class does not get a new bean--it uses the same bean over and over.
Listener which implements: BeanFactoryPostProcessor, BeanPostProcessor, BeanFactoryAware, DisposableBean and attempt to call destroy() on all Disposable bean instances; something like this but for my custom scope only. This seems to fail in that nothing is explicitly ending the lifecycle of the beans, despite the fact that I'm calling customScope.clear() when I receive the scope ending event; ending the scope doesn't seem to translate to "end all beans associated with this scope".
I've read Spring documentation extensively and it seems to be clear that Spring doesn't manage the lifecycle of these custom beans in that it doesn't know when or how they should be destroyed, which means that it must be told when and how to destroy them; I've tried to read and understand the Session and Request scopes as provided by Spring so that I can mimic this but am missing something (again, these are not available to me since this is not a web-aware application and I'm not using HttpRequests and it is a non-trivial change in our application's structure)
Is anyone out there able to point me in the right direction?
I have the following code examples:
Xml Context Configuration:
<int-ip:tcp-connection-factory id="serverConnectionFactory" type="server" port="19000"
serializer="javaSerializer" deserializer="javaDeserializer"/>
<int-ip:tcp-inbound-gateway id="inGateway" connection-factory="serverConnectionFactory"
request-channel="incomingServerChannel" error-channel="errorChannel"/>
<int:channel id="incomingServerChannel" />
<int:chain input-channel="incomingServerChannel">
<int:service-activator ref="transactionController"/>
</int:chain>
TransactionController (handles request):
#Component("transactionController")
public class TransactionController {
#Autowired
private RequestWrapper requestWrapper;
#ServiceActivator
public String handle(final Message<?> requestMessage) {
// object is passed around through various phases of application
// object is changed, things are added, and finally, a response is generated based upon this data
tcpRequestCompletePublisher.publishEvent(requestWrapper, "Request lifecycle complete.");
return response;
}
}
TcpRequestScope (scope definition):
#Component
public class TcpRequestScope implements Scope {
private final ThreadLocal<ConcurrentHashMap<String, Object>> scopedObjects =
new InheritableThreadLocal<ConcurrentHashMap<String, Object>>({
#Override
protected ConcurrentHashMap<String, Object> initialValue(){
return new ConcurrentHashMap<>();
}
};
private final Map<String, Runnable> destructionCallbacks =
Collections.synchronizedMap(new HashMap<String, Runnable>());
#Override
public Object get(final String name, final ObjectFactory<?> objectFactory) {
final Map<String, Object> scope = this.scopedObjects.get();
Object object = scope.get(name);
if (object == null) {
object = objectFactory.getObject();
scope.put(name, object);
}
return object;
}
#Override
public Object remove(final String name) {
final Map<String, Object> scope = this.scopedObjects.get();
return scope.remove(name);
}
#Override
public void registerDestructionCallback(final String name, final Runnable callback) {
destructionCallbacks.put(name, callback);
}
#Override
public Object resolveContextualObject(final String key) {
return null;
}
#Override
public String getConversationId() {
return String.valueOf(Thread.currentThread().getId());
}
public void clear() {
final Map<String, Object> scope = this.scopedObjects.get();
scope.clear();
}
}
TcpRequestCompleteListener:
#Component
public class TcpRequestCompleteListener implements ApplicationListener<TcpRequestCompleteEvent> {
#Autowired
private TcpRequestScope tcpRequestScope;
#Override
public void onApplicationEvent(final TcpRequestCompleteEvent event) {
// do some processing
// clear all scope related data (so next thread gets clean slate)
tcpRequestScope.clear();
}
}
RequestWrapper (object we use throughout request lifecycle):
#Component
#Scope(scopeName = "tcpRequestScope", proxyMode =
ScopedProxyMode.TARGET_CLASS)
public class RequestWrapper implements Serializable, DisposableBean {
// we have many fields here which we add to and build up during processing of request
// actual request message contents will be placed into this class and used throughout processing
#Override
public void destroy() throws Exception {
System.out.print("Destroying RequestWrapper bean");
}
}
After many months and a few more attempts, I finally stumbled across some articles which pointed me in the right direction. Specifically, references in David Winterfeldt's blog post helped me understand the SimpleThreadScope which I had previously read, and was well aware of the fact that Spring makes no attempt to clear the scope after its lifecycle is complete, however, his article demonstrated the missing link for all previous implementations I had seen.
Specifically, the missing links were static references to ThreadScopeContextHolder in ThreadScope class in his implementation (in my proposed implementation above I called mine TcpRequestScope; the rest of this answer uses David Winterfeldt's terms since his reference documentation will prove most useful, and he wrote it).
Upon closer inspection of the Custom Thread Scope Module I noticed I was missing the ThreadScopeContextHolder, which contained a static reference to a ThreadLocal, which contains a ThreadScopeAttributes object which is what holds in-scope objects.
Some minor differences between David's implementation and my final one were, after Spring Integration sends its response, I use a ChannelInterceptor to clear the thread scope, since I'm using Spring Integration. In his examples, he extended threads which included a call to the context holder as part of a finally block.
How I'm clearing the scope attributes / beans:
public class ThreadScopeInterceptor extends ChannelInterceptorAdapter {
#Override
public void afterSendCompletion(final Message<?> message, final MessageChannel channel, final boolean sent,
#Nullable final Exception exception) {
// explicitly clear scope variables
ThreadScopeContextHolder.clearThreadScopeState();
}
Additionally, I added a method in the ThreadScopeContextHolder which clears the ThreadLocal:
public class ThreadScopeContextHolder {
// see: reference document for complete ThreadScopeContextHolder class
/**
* Clears all tcpRequest scoped beans which are stored on the current thread's ThreadLocal instance by calling
* {#link ThreadLocal#remove()}.
*/
public static void clearThreadScopeState() {
threadScopeAttributesHolder.remove();
}
}
While I'm not absolutely certain that there will not be memory leaks due to the ThreadLocal usage, I believe this will work as expected since I am calling ThreadLocal.remove(), which will remove the only reference to the ThreadScopeAttributes object, and therefore open it up to garbage collection.
Any improvements are welcomed, especially in terms of usage of ThreadLocal and how this might cause problems down the road.
Sources:
David Winterfeldt's Custom Thread Scope Module
Spring By Example Custom Thread Scope Module github (See David Winterfeldt's example above)
jyore's spring scopes (specifically, thread scope)
David Noel's (Devbury) Spring Boot Starter Thread Scope

Is there a nice way to access Guice Request scoped items from child threads and scope things locally to those threads? [duplicate]

I am using Guice's RequestScoped and Provider in order to get instances of some classes during a user request. This works fine currently. Now I want to do some job in a background thread, using the same instances created during request.
However, when I call Provider.get(), guice returns an error:
Error in custom provider, com.google.inject.OutOfScopeException: Cannot
access scoped object. Either we are not currently inside an HTTP Servlet
request, or you may have forgotten to apply
com.google.inject.servlet.GuiceFilter as a servlet
filter for this request.
afaik, this is due to the fact that Guice uses thread local variables in order to keep track of the current request instances, so it is not possible to call Provider.get() from a thread different from the thread that is handling the request.
How can I get the same instances inside new threads using Provider? It is possible to achieve this writing a custom scope?
I recently solved this exact problem. There are a few things you can do. First, read up on ServletScopes.continueRequest(), which wraps a callable so it will execute as if it is within the current request. However, that's not a complete solution because it won't forward #RequestScoped objects, only basic things like the HttpServletResponse. That's because #RequestScoped objects are not expected to be thread safe. You have some options:
If your entire #RequestScoped hierarchy is computable from just the HTTP response, you're done! You will get new instances of these objects in the other thread though.
You can use the code snippet below to explicitly forward all RequestScoped objects, with the caveat that they will all be eagerly instantiated.
Some of my #RequestScoped objects couldn't handle being eagerly instantiated because they only work for certain requests. I extended the below solution with my own scope, #ThreadSafeRequestScoped, and only forwarded those ones.
Code sample:
public class RequestScopePropagator {
private final Map<Key<?>, Provider<?>> requestScopedValues = new HashMap<>();
#Inject
RequestScopePropagator(Injector injector) {
for (Map.Entry<Key<?>, Binding<?>> entry : injector.getAllBindings().entrySet()) {
Key<?> key = entry.getKey();
Binding<?> binding = entry.getValue();
// This is like Scopes.isSingleton() but we don't have to follow linked bindings
if (binding.acceptScopingVisitor(IS_REQUEST_SCOPED)) {
requestScopedValues.put(key, binding.getProvider());
}
}
}
private final BindingScopingVisitor<Boolean> IS_REQUEST_SCOPED = new BindingScopingVisitor<Boolean>() {
#Override
public Boolean visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) {
return scopeAnnotation == RequestScoped.class;
}
#Override
public Boolean visitScope(Scope scope) {
return scope == ServletScopes.REQUEST;
}
#Override
public Boolean visitNoScoping() {
return false;
}
#Override
public Boolean visitEagerSingleton() {
return false;
}
};
public <T> Callable<T> continueRequest(Callable<T> callable) {
Map<Key<?>, Object> seedMap = new HashMap<>();
for (Map.Entry<Key<?>, Provider<?>> entry : requestScopedValues.entrySet()) {
// This instantiates objects eagerly
seedMap.put(entry.getKey(), entry.getValue().get());
}
return ServletScopes.continueRequest(callable, seedMap);
}
}
I have faced the exact same problem but solved it in a different way. I use jOOQ in my projects and I have implemented transactions using a request scope object and an HTTP filter.
But then I created a background task which is spawned by the server in the middle of the night. And the injection is not working because there is no request scope.
Well. The solutions is simple: create a request scope manually. Of course there is no HTTP request going on but that's not the point (mostly). It is the concept of the request scope. So I just need a request scope that exists alongside my background task.
Guice has an easy way to create a request scope: ServletScope.scopeRequest.
public class MyBackgroundTask extends Thread {
#Override
public void run() {
RequestScoper scope = ServletScopes.scopeRequest(Collections.emptyMap());
try ( RequestScoper.CloseableScope ignored = scope.open() ) {
doTask();
}
}
private void doTask() {
}
}
Oh, and you probably will need some injections. Be sure to use providers there, you want to delay it's creation until inside the created scope.
Better use ServletScopes.transferRequest(Callable) in Guice 4

Dynamic per REST(Jersey) request binding of configurations in Guice

We are using Guice in our project for DI. Currently we have some configurations(properties) that we load a t server startup from a file. These are then bound to all the components & used for all the requests.
But now, we have multiple property files & load them at startup. These configurations can be different per REST(Jersey) request as they depend on the input.
So, we need to bind these configurations dynamically for each request. I looked into Guice API for #RequestScoped, but did not find anything specificallyu helpful.
There are few questions similar to this, but no luck yet. Can you please help me with this.
I'm providing 2 ways of doing this and both are request scoped.
Using HttpServletRequest, for classes where you can Inject request object.
Using ThreadLocal, Generic way. It can be used in any class.
(NOTE: This method wouldn't work if your creating new threads in your code and want to access the value. In which case you'll have to pass the values through Objects to those threads)
I meant something like this:
public class RequestFilter implements ContainerRequestFilter {
#Context
private HttpServletRequest request;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
List listOfConfig = //load Config;
request.setAttribute("LOADED_CONFIG",listOfConfig);
// If you want to access this value at some place where Request object cannot be injected (like in service layers, etc.) Then use below ThreadLocals.
ThreadLocalWrapper.getInstance().get().add("adbc"); // In general add your config here, instead of abdc.
}
}
My ThreadLocalWrapper looks like this:
public class ThreadLocalWrapper {
private static ThreadLocal<List<String>> listOfStringLocals; // You can modify this to a list of Object or an Object by itself.
public static synchronized ThreadLocal<List<String>> getInstance() {
if (listOfStringLocals == null) {
listOfStringLocals = new ThreadLocal<List<String>>() {
#Override
protected List<String> initialValue() {
return new ArrayList<String>();
}
};
}
return listOfStringLocals;
}
}
To Access the value:
In Controller - Inject HttpServletRequest Object and do getAttribute() to get the value. Since HttpServletRequest Object is requestScoped, you can set the loaded config. into this and access it in your controller's using request Object again.
In Any other part of the code - If HttpServletRequest is not available then you can always use the ThreadLocal example shown. To access this value.
public class GuiceTransactionImpl implements GuiceTransaction {
private String value = "";
public GuiceTransactionImpl(String text) {
value = text;
}
#Override
public String returnSuccess() {
return value + " Thread Local Value " + ThreadLocalWrapper.getInstance().get();
}
}

Class variable vs passing parameter in java - design issue

Say I have 2 classes in an SOA model application..
Service class - which takes request and returns response
For further processing (say, business logic/parsing/dao etc), it passes the request to a SvcBusiness class.
Question is, should SvcBusiness class use the request as its class variable or should it just use the request in one of it's business methods? It is possible that request needs to be passed to other lower layers like DAO layer. Should those classes also use request as a class variable or should the request be just part of a method?
ServiceImpl class:
public class ServiceImpl {
public Response getDataForType1Request(Request type1) {
SvcBusiness buzclazz = new SvcBusiness();
return buzclazz.doOperationForType1(type1);
}
public Response getDataForType2Request(Request type2) {
SvcBusiness buzclazz = new SvcBusiness();
return buzclazz.doOperationForType2(type2);
}
}
Option 1: when request is passed as a parameter.
public class SvcBusiness {
public Response doOperationForType1(Request type1) {
// do business and return response1
}
public Response doOperationForType2(Request type2) {
// do business and return response2
}
}
Option 2: request is set as a class variable. In this scenario.. ServiceImpl will pass the request to SvcBusiness constructor when the object is created.. and will simply call execute() method.
public class SvcBusiness {
private Request request;
public SvcBusiness(Request request) {
this.request = request;
}
private Response doOperationForType1() {
// do business and return response1
}
private Response doOperationForType2() {
// do business and return response2
}
public Response execute() {
// if type1 request call doOperationForType1()
// if type2 request call doOperationForType1()
}
}
Please help! What are the advantages and disadvantages of both? Is there a design pattern to address this scenario?
Don't use the Request (and Response) further down in your class hierarchy! The service (and everything called by the service) may be called from somewhere else, where there is no such thing as a Request. And then you will have a problem with filling that parameter. Use an own data model in the service, and extract and convert everything you need for that from the Request.
Fully agree with Uwe's answer. However, if you still want to use Request class, it'll be less harmful as a parameter (The way Servlets work). Otherwise, you'd have to deal with synchronization on a highly probable multithreaded environment.
When I face a problem like this I always wonder if I really need an object. Usually I use the option 1 but creating all methods as static. As those methods don't rely in the current object state (there are no instance attributes), I save some memory just not creating such objects (other option is just implement the Singleton pattern).
public class SvcBusiness {
public static Response doOperationForType1(Request type1) {
// do business and return response1
}
public Response doOperationForType2(Request type2) {
// do business and return response2
}
}

Categories