I am planning to use EJBContext to pass some properties around from the application tier (specifically, a message-driven bean) to a persistence lifecycle callback that cannot directly be injected or passed parameters (session listener in EclipseLink, entity lifecycle callback, etc.), and that callback is getting the EJBContext via JNDI.
This appears to work but are there any hidden gotchas, like thread safety or object lifespan that I'm missing? (Assume the property value being passed is immutable like String or Long.)
Sample bean code
#MessageDriven
public class MDB implements MessageListener {
private #Resource MessageDrivenContext context;
public void onMessage(Message m) {
context.getContextData().put("property", "value");
}
}
Then the callback that consumes the EJBContext
public void callback() {
InitialContext ic = new InitialContext();
EJBContext context = (EJBContext) ic.lookup("java:comp/EJBContext");
String value = (String) context.getContextData().get("property");
}
What I'm wondering is, can I be sure that the contextData map contents are only visible to the current invocation/thread? In other words, if two threads are running the callback method concurrently, and both look up an EJBContext from JNDI, they're actually getting different contextData map contents?
And, how does that actually work - is the EJBContext returned from the JNDI lookup really a wrapper object around a ThreadLocal-like structure ultimately?
I think in general the contract of the method is to enable the communication between interceptors + webservice contexts and beans. So the context should be available to all code, as long as no new invocation context is created. As such it should be absolutely thread-safe.
Section 12.6 of the EJB 3.1 spec says the following:
The InvocationContext object provides metadata that enables
interceptor methods to control the behavior of the invocation chain.
The contextual data is not sharable across separate business method
invocations or lifecycle callback events. If interceptors are invoked
as a result of the invocation on a web service endpoint, the map
returned by getContextData will be the JAX-WS MessageContext
Furthermore, the getContextData method is described in 4.3.3:
The getContextData method enables a business method, lifecycle callback method, or timeout method to retrieve any interceptor/webservices context associated with its invocation.
In terms of actual implementation, JBoss AS does the following:
public Map<String, Object> getContextData() {
return CurrentInvocationContext.get().getContextData();
}
Where the CurrentInvocationContext uses a stack based on a thread-local linked list to pop and push the current invocation context.
See org.jboss.ejb3.context.CurrentInvocationContext. The invocation context just lazily creates a simple HashMap, as is done in org.jboss.ejb3.interceptor.InvocationContextImpl
Glassfish does something similar. It also gets an invocation, and does this from an invocation manager, which also uses a stack based on a thread-local array list to pop and push these invocation contexts again.
The JavaDoc for the GlassFish implementation is especially interesting here:
This TLS variable stores an ArrayList. The ArrayList contains
ComponentInvocation objects which represent the stack of invocations
on this thread. Accesses to the ArrayList dont need to be synchronized
because each thread has its own ArrayList.
Just as in JBoss AS, GlassFish too lazily creates a simple HashMap, in this case in com.sun.ejb.EjbInvocation. Interesting in the GlassFish case is that the webservice connection is easier to spot in the source.
I can't help you directly with your questions regarding EJBContext, since the getContextData method was added in JEE6 there is still not much documentation about it.
There is however another way to pass contextual data between EJBs, interceptors and lifecycle callbacks using the TransactionSynchronizationRegistry. The concept and sample code can be found in this blog post by Adam Bien.
javax.transaction.TransactionSynchronizationRegistry holds a Map-like structure and can be used to pass state inside a transaction. It works perfectly since the old J2EE 1.4 days and is thread-independent.
Because an Interceptor is executed in the same transaction as the ServiceFacade, the state can be even set in a #AroundInvoke method. The TransactionSynchronizationRegistry (TSR) can be directly injected into an Interceptor.
The example there uses #Resource injection to obtain the TransactionSynchronizationRegistry, but it can also be looked up from the InitialContext like this:
public static TransactionSynchronizationRegistry lookupTransactionSynchronizationRegistry() throws NamingException {
InitialContext ic = new InitialContext();
return (TransactionSynchronizationRegistry)ic.lookup("java:comp/TransactionSynchronizationRegistry");
}
Related
We have several legacy java-services with RMI-api, implemented by the old JRMP approach requiring 'rmic' pre-compilation.
As part of migrating everything to latest JDK,
I am also trying to rewrite the RMI stuff to the more current approach, where the implementation-classes extend from UnicastRemoteObject, thus getting rid of the rmic pre-compilation step.
Following a simple example, like here:
https://www.mkyong.com/java/java-rmi-hello-world-example/
but I have not been able to find such example with commit/rollback transaction-logic.
In the current legacy-code, all transaction-logic is handled in a single, common method invokeObject() in the JRMP container-code that will intercept all RMI api-calls in one place,
and will simply commit if the RMI-call is successful, or rollback if an Exception was thrown.
I haven't been able to figure out how to do this in the new approach with no JRMP container present.
Obviously, I do not want to code commit/rollback-logic into every single api-method (there are many dozens of them),
but still keep that uniform logic in one place.
Any advice, hints, references, etc, how to intercept all RMI-calls in a single point to implement the transaction-logic?
To begin with, I agree with #df778899 the solution he provides is a robust solution. Although,I will give you an alternative choice if you don't want to work with spring framework and you want to dig it further.
Interceptors provide a powerful and flexible design include invocation monitoring, logging, and message routing. In some sense, the key value you are looking is a kind of RMI-level AOP (aspect-oriented programming) support
Generally speaking:
it is not fair to ask RMI to directly support such capabilities as it
is only a basic remote method invocation primitive, while CORBA ORB is
at a layer close to what the J2EE EJB (Enterprise JavaBean) container
offers. In the CORBA specification, service context is directly
supported at the IIOP level (GIOP, or General Inter-Orb Protocol) and
integrated with the ORB runtime. However, for RMI/IIOP, it is not easy
for applications to utilize the underlying IIOP service-context
support, even when the protocol layer does have such support. At the
same time, such support is not available when RMI/JRMP (Java Remote
Method Protocol) is used. As a result, for RMI-based distributed
applications that do not use, or do not have to use, an ORB or EJB
container environment, the lack of such capabilities limits the
available design choices, especially when existing applications must
be extended to support new infrastructure-level functions. Modifying
existing RMI interfaces often proves undesirable due to the
dependencies between components and the huge impact to client-side
applications. The observation of this RMI limitation leads to the
generic solution that I describe in this article
Despite all the above
The solution is based on Java reflection techniques and some common
methods for implementing interceptors. More importantly, it defines an
architecture that can be easily integrated into any RMI-based
distributed application design.
The solution below is demonstrated through an example implementation that supports the transparent passing of transaction-context data, such as a transaction ID (xid), with RMI. The solution contains the following three important components:
RMI remote interface naming-function encapsulation and interceptor plug-in
Service-context propagation mechanism and server-side interface support
Service-context data structure and transaction-context propagation support
The implementation assumes that RMI/IIOP is used. However, it by no
means implies that this solution is only for RMI/IIOP. In fact, either
RMI/JRMP or RMI/IIOP can be used as the underlying RMI environments,
or even a hybrid of the two environments if the naming service
supports both
Naming-function encapsulation
First we encapsulate the naming function that provides the RMI remote
interface lookup, allowing interceptors to be transparently plugged
in. Such an encapsulation is always desirable and can always be found
in most RMI-based applications. The underlying naming resolution
mechanism is not a concern here; it can be anything that supports JNDI
(Java Naming and Directory Interface). In this example, to make the
code more illustrative, we assume all server-side remote RMI
interfaces inherit from a mark remote interface ServiceInterface,
which itself inherits from the Java RMI Remote interface. Figure
shows the class diagram, which is followed by code snippets that I
will describe further
RMI invocation interceptor
To enable the invocation interceptor, the original RMI stub reference
acquired from the RMI naming service must be wrapped by a local proxy.
To provide a generic implementation, such a proxy is realized using a
Java dynamic proxy API. In the runtime, a proxy instance is created;
it implements the same ServiceInterface RMI interface as the wrapped
stub reference. Any invocation will be delegated to the stub
eventually after first being processed by the interceptor. A simple
implementation of an RMI interceptor factory follows the class diagram
shown in Figure
package rmicontext.interceptor;
public interface ServiceInterfaceInterceptorFactoryInterface {
ServiceInterface newInterceptor(ServiceInterface serviceStub, Class serviceInterfaceClass) throws Exception;
}
package rmicontext.interceptor;
public class ServiceInterfaceInterceptorFactory
implements ServiceInterfaceInterceptorFactoryInterface {
public ServiceInterface newInterceptor(ServiceInterface serviceStub, Class serviceInterfaceClass)
throws Exception {
ServiceInterface interceptor = (ServiceInterface)
Proxy.newProxyInstance(serviceInterfaceClass.getClassLoader(),
new Class[]{serviceInterfaceClass},
new ServiceContextPropagationInterceptor(serviceStub)); // ClassCastException
return interceptor;
}
}
package rmicontext.interceptor;
public class ServiceContextPropagationInterceptor
implements InvocationHandler {
/**
* The delegation stub reference of the original service interface.
*/
private ServiceInterface serviceStub;
/**
* The delegation stub reference of the service interceptor remote interface.
*/
private ServiceInterceptorRemoteInterface interceptorRemote;
/**
* Constructor.
*
* #param serviceStub The delegation target RMI reference
* #throws ClassCastException as a specified uncaught exception
*/
public ServiceContextPropagationInterceptor(ServiceInterface serviceStub)
throws ClassCastException {
this.serviceStub = serviceStub;
interceptorRemote = (ServiceInterceptorRemoteInterface)
PortableRemoteObject.narrow(serviceStub, ServiceInterceptorRemoteInterface.class);
}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
// Skip it for now ...
}
}
To complete the ServiceManager class, a simple interface proxy cache is implemented:
package rmicontext.service;
public class ServiceManager
implements ServiceManagerInterface {
/**
* The interceptor stub reference cache.
* <br><br>
* The key is the specific serviceInterface sub-class and the value is the interceptor stub reference.
*/
private transient HashMap serviceInterfaceInterceptorMap = new HashMap();
/**
* Gets a reference to a service interface.
*
* #param serviceInterfaceClassName The full class name of the requested interface
* #return selected service interface
*/
public ServiceInterface getServiceInterface(String serviceInterfaceClassName) {
// The actual naming lookup is skipped here.
ServiceInterface serviceInterface = ...;
synchronized (serviceInterfaceInterceptorMap) {
if (serviceInterfaceInterceptorMap.containsKey(serviceInterfaceClassName)) {
WeakReference ref = (WeakReference) serviceInterfaceInterceptorMap.get(serviceInterfaceClassName);
if (ref.get() != null) {
return (ServiceInterface) ref.get();
}
}
try {
Class serviceInterfaceClass = Class.forName(serviceInterfaceClassName);
ServiceInterface serviceStub =
(ServiceInterface) PortableRemoteObject.narrow(serviceInterface, serviceInterfaceClass);
ServiceInterfaceInterceptorFactoryInterface factory = ServiceInterfaceInterceptorFactory.getInstance();
ServiceInterface serviceInterceptor =
factory.newInterceptor(serviceStub, serviceInterfaceClass);
WeakReference ref = new WeakReference(serviceInterceptor);
serviceInterfaceInterceptorMap.put(serviceInterfaceClassName, ref);
return serviceInterceptor;
} catch (Exception ex) {
return serviceInterface; // no interceptor
}
}
}
}
You can find more details in the following guideline here. It is important to understand all this above if you desire to make it from scratch, in contrast with Spring-AOP Framework robust solution.In addition,I think you will find very interesting the Spring Framework plain source code for implementing an RmiClientInterceptor. Take another look here also.
You might consider using Spring with RMI. It offers a simplified way to use transactions. You just set some persistence settings from the #EnableTransactionManagement annotation and it manages transactions for you at a point defined by #Transactional. It can be a class or methods of a class.
example code here
The explanation is in the project README.
I don't know if you've already considered this, one possibility that would fit well with the dual requirement of RMI and transactional boundaries is clearly Spring. An example of Spring Remoting is here.
The #Transactional annotation is very widely used for declarative transaction management - Spring will automatically wrap your bean in an AOP transaction advisor.
These two would then fit together well, for example with a single transactional bean that could be exported as a remote service.
The Spring Remoting link above is based around Spring Boot, which is an easy way to get started. By default Boot would want to bring in an embedded server to the environment, though this can be disabled. Equally there are other options like a standalone AnnotationConfigApplicationContext, or a WebXmlApplicationContext within an existing web application.
Naturally with a question asking for recommendations, there will an element of opinion in any reply - I would be disappointed not to see some other suggestions shortly.
At a project I am working on, we have the need to add some additional parameters to our ejb calls.
We don't put those parameters as regular ejb interface parameters because we already have lots of interfaces and changing most of them would be a pain (plus it's not related to the logic, these are some additional parameters being saved in the database, call it a side effect).
So to the point, we use weblogic as our application server (10.3.4, Java 6, JavaEE 5) and the solution we found for this problem was to make a wrapper ejb that will accept the real method target, its arguments and of course the additional parameters.
The wrapper will then store the additional parameters on the transaction, create a new initial context and lookup the target ejb.
The wrapper ejb function looks like this:
public Object invokeWithAdditionalParameters (MethodSignature methodSignature, Object[] args, SomeAdditionalParameter p) {
transaction.putResource("additionalParam", p);
InitialContext ctx = new InitialContext();
Object service = ctx.lookup(methodSignature.buildLookupName());
return methodSignature.getMethod().invoke(service, args);
}
MethodSignature holds the targeted ejb method we would like to invoke.
I don't know if this solution is acceptable and if we should cache our InitialContexts, as we are already in the server and don't need to make expensive network calls to the jndi tree, but maybe I'm wrong...
Thank you,
Aviad.
Before adding CDI into our application I had created a resource that used the #Suspended AsyncResponse object to implement long polling for a chat client. What I did was create a new newSingleThreadExecutor() and submit a Runnable to it that used .wait(30000) on a message list until notification that a new message was sent. Inside that task I used the HttpServletRequest which was obtained using #Context and everything worked perfectly.
However once we added CDI to our application and even without making the resource class a bean (scanning only annotated beans and we didn't give it any scope annotation) I got a runtime exception that the request object INSIDE the Runnable task couldn't be accessed because of an illegal state exception:
Method threw 'java.lang.IllegalStateException' exception. Cannot evaluate com.sun.proxy.$Proxy74.toString()
I'm not really sure why this happens but I know it is CDI related since it refers to a proxy object. One guess is that the resource class itself has become CDI scoped and that scope can't be accessed from a different thread? I read somewhere that manually started threads are not managed and thus can't have access to any scope related objects. However how did this use to work until CDI was implemented?
Right now I THINK I've solved the issue (that is releasing the thread servicing request I/O and having a worker take over the waiting until notified) using jersey's #ManagedAsync annotation which supposedly has the whole method be run in an internal jersey executor service. Is this correct? Also in that case, is there any need of the AsyncResponse object?
EDIT: I have NOT solved the issue. #ManagedAsync worked when the resource class was not defined as a CDI bean. After making it #RequestScoped, whenever I try to call the method I get the following exception
org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped
I think this is because the request can end before the async thread has finished which means all scope objects (like HttpServletRequest) will be destroyed and thus we won't have access to them. Is there a way to used #ManagedAsync in a #RequestScoped bean and make use of #Context HttpServletRequest??
TL;DR:
How can I have access to a context resource inside a manually started thread?
Why did I have access to the request object before CDI was implemented?
Is it possible to use #ManagedAsync in a #RequestScoped cdi bean?
Old method:
#GET
#Path("method")
public void method(#Context HttpServletRequest request, #Suspended AsyncResponse ar) {
//request object was accessible here
Executors.newSingleTHreadExecutor().submit(() -> {
//request object was also accessible here but lost access after implementing CDI.
Object o = foo.bar(request);
ar.resume(Response.ok(o).build());
});
}
Current non-working method:
#GET
#Path("method")
#ManagedAsync
public void method(#Context HttpServletRequest request, #Suspended AsyncResponse ar) {
Object o = foo.bar(request);
ar.resume(Response.ok(o).build()); //Is there any point to this?
}
To answer your question - no. You cannot use async and request scoped objects. Async support is lacking in CDI - see also https://issues.jboss.org/browse/CDI-452
Could I have multiple threads use the same static instance of HttpComponentsClientHttpRequestFactory to safely create their respective ClientHttpRequest?
I am not able to find any manual that would tell me the answer.
I am presuming it is thread-safe simply because the all createRequest methods actually perform a new instantiation of a request object. For example,
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri);
postProcessHttpRequest(httpRequest);
return new HttpComponentsClientHttpRequest(getHttpClient(), httpRequest, createHttpContext(httpMethod, uri));
}
But then it calls a few other methods which may not be thread-safe.
In fact, if you do know the answer, where is the manual that would tell me the thread safety of anything in Spring?
Generally, any class within Spring infrastructure ending in Factory is thread-safe once it's initialized (i.e., once the constructor is called and the bean is initialized with its property values). Technically it's not thread-safe between constructor call and property injection, but all of the Spring ApplicationContext implementations I know of block requests for beans until context initialization is complete.
Bottom line is: don't create Factory objects outside of Spring manually and you should be fine.
I am developing a RESTful Web Service and while reading the Jersey documentation I came across an annotation #Singleton
In my web service I am mostly returning data based on the unique keys provided as parameter.
An analogy would be return all the information of a Student when the Student_Id is passed.
So my question is when #Singleton would be suited in such kind of Web Services?
As per documentation for #RequestScoped
If the resource is used more than one time in the request processing, always the same instance will be used.
Then in that case we should not bother to use #Singleton right?
Also what could be the use cases where we have to make a new instance for every request?
I did have a look at this post but my question was not answered.
By default Jersey creates a new instance of the resource class for every request. So if you don't annotate the Jersey resource class, it implicitly uses #RequestScoped scope. It is stated in Jersey documentation:
Default lifecycle (applied when no annotation is present). In this
scope the resource instance is created for each new request and used
for processing of this request. If the resource is used more than one
time in the request processing, always the same instance will be used.
This can happen when a resource is a sub resource is returned more
times during the matching. In this situation only on instance will
server the requests.
Most cases you use this default setting so you don't use #Singleton scope. You can also create a singleton Jersey resource class by using #Singleton annotation. Then you need to register the singleton class in the MyApplication class, e.g.,
#Path("/resource")
#Singleton
public class JerseySingletonClass {
//methods ...
}
public class MyApplication extends ResourceConfig {
/*Register JAX-RS application components.*/
public MyApplication () {
register(JerseySingletonClass.class);
}
}
Came along this question, because for the first time I had a use case for not using #Singleton annotation.
Singleton is a design pattern, you should use it if:
The object you are "singletonizing" keeps a state that must be shared and kept unique (example: a global counter)
Generally, I design REST API without keeping a state, everything is handled in the method (full closure): so generally all my resources are singletons (use case: better performance)
That said, today I found this use case for not using Singleton:
#Path("/someendpoint/{pathparam}/somethingelse/")
//#Singleton
public class MyResource {
#PathParam("pathparam")
private String pathparam;
}
Using this, I'm bounding the path param to my instance, so it must be RequestScoped.
Generally, I'd have put #PathParam annotation in every method, so #Singleton would have been right on the class.
I'm not sure about the performances however, creating and destroying an object isn't a free operation
In most cases default scope #RequestScoped should be sufficient for your needs.
#Singleton may hold state. I had the problem when my endpoint was annotated as #Singleton so it reused the same EntityManager during concurrent calls. After removing #Singleton, during concurrent calls, different EntityManager object instances are used. If endpoint calls are subsequent, it may be that previous/old EntityManager will be used. - Jersey, Guice and Hibernate - EntityManager thread safety
There is actually a use case specified in the Jersey 2 manual for using the SseBroadcaster when serving Server-Sent events, it is covered in this provided example
The BroadcasterResource resource class is annotated with #Singleton annotation which tells Jersey runtime that only a single instance of the resource class should be used to serve all the incoming requests to /broadcast path. This is needed as we want to keep an application-wide single reference to the private broadcaster field so that we can use the same instance for all requests. Clients that want to listen to SSE events first send a GET request to the BroadcasterResource, that is handled by the listenToBroadcast() resource method.
Using the #Singleton, The application will only contain one SseBroadcaster for all incoming requests, one such broadcaster is enough to serve multiple clients, so it only needs to be instantiated once!
JAX-RS SSE API defines SseBroadcaster which allows to broadcast individual events to multiple clients.