I’ve tried CDI injection and #EJB injection of Stateless EJBs in a Rivr dialog. They don’t work.
I’ve also tried JNDI lookup of the EJBs through the Global JNDI name but I get following error (note I am using java:global but I get this message):
A JNDI operation on a java:comp/env name cannot be completed because the current thread is not associated with a Java Enterprise Edition application component. This condition can occur when the JNDI client using the java:comp/env name does not occur on the thread of a server application request. Make sure that a Java EE application does not run JNDI operations on java:comp/env names within static code blocks or in threads created by that application. Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on java:comp/env names.
Is there anyway I can inject or locate CDI #Named or EJBs in a Rivr dialog?
thanks
Ignacio
I examined the Spring example in Rivr cookbook and found that the DialogFactories are executed in the ServletThread. This allowed me to perform a standard JNDI lookup using the Global JNDI name successfully and pass the EJBs to the Dialog being created.
Rivr team confirmed this by email and I am now successfully accessing EJBs that way.
I could not perform standard #Inject or #EJB injections but the JNDI "traditional" solution worked for me.
Related
I am doing EJB lookup on application deployed on liberty inside a Listener class (sessionDestroyed method).
I am not starting any new thread. Still getting the below error
javax.naming.NamingException: CWNEN1000E: "A JNDI operation on a java:comp/env name cannot be completed because the current thread is not associated with a Java Enterprise Edition application component. This condition can occur when the JNDI client using the java:comp/env name does not occur on the thread of a server application request. Make sure that a Java EE application does not run JNDI operations on java:comp/env names within static code blocks or in threads created by that application. Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on java:comp/env names"
Any thoughts/pointers regarding this ?
Questions about ejb session bean behavior when used as injected bean instances.
I'm not 100% sure how this works. I guess it from practice and from reading documents on the subject.
I want to know how #EJB annotation is processed by container in detail.
Session bean have interfaces, impl class, deployment descriptor. We package them in ejb jar.
What is putted in global JNDI by container? Static references to
business interfaces ?
How and when global JNDI is read from ?
When component JNDI ENC is populated with ejb reference ?
Is this reference in JNDI ENC (java:comp/env/beanB) is reference to
session bean component interface, session bean instance proxy or
session bean instance ? Is there difference for SLSB and SFSB ?
With #EJB annotation on field does every new ejb session bean
instance get new instance of injected ejb in the annotated field or
all ejb instances share the same injected ejb session bean instance
?
Does ejb injection by lookup (on session context) provide always new
injected ejb instance, example: calling ctx.lookup(ejbReference) in
loop ?
In EJB 3.0, the JNDI names are vendor-specific (if available at all; in theory, a container could support EJB references only), but vendors typically return an EJB reference/proxy. In EJB 3.1, the specification requires the EJB container to make specific java:global, java:app, and java:module names available, and the object returned from these lookups must be an EJB reference/proxy.
The global JNDI is accessed when you perform a JNDI lookup. The container might access the global JNDI names in other cases (e.g., when resolving #EJB(lookup="java:app/...")).
It's undefined when the container populates java:, but the contents must be available before lifecycle callback or business methods are invoked on the component instance.
#EJB/<ejb-ref>/<ejb-local-ref> ensure lookups always return an EJB reference/proxy and never an actual bean instance. The proxy ensures that all container services are performed (security, transaction, remoting, etc.) before invoking an actual bean instance. For SLSB, an arbitrary bean instance will be invoked, and the same or different actual instance might be invoked depending on the thread, concurrency, timing, vendor-specific configuration, etc. For SFSB, a bean instance with a specific identity will be invoked; you are likely to get the same bean instance, but you might not if the EJB container has passivated the actual bean instance, but reactivation should result in an instance with equivalent state. For singleton session bean in EJB 3.1, you are guaranteed the singleton bean instance will be invoked.
It's undefined whether you get the same proxy instance. For SLSB and singleton beans, injection or lookup could return a single proxy that delegates to the actual bean instance as mentioned above. For SFSB, the proxy is basically required to be a separate instance per injection or lookup since the proxy must store some state with the identity so it can invoke the specific actual bean instance.
It's undefined what the container does, but injection is typically implemented by containers using Context.lookup followed by Field.set (or Method.invoke for setter method injection). Regardless, the instance handling is as described above.
I am studying up on EJB 3 from the book EJB in Action and this book in chapter 5 discusses about environment naming context(ENC). It says this :
If you know how JNDI references worked in EJB 2, you’re familiar with
the environment naming context (ENC). ENC allows portability of the
application without having to depend on global JNDI names. Global JNDI
names for resources differ between application server implementations,
and ENC allows you to use a JNDI location that starts with
java:comp/env/ instead of hard-coding the actual global JNDI name. EJB
3 essentially assumes that all JNDI names used in code are local
references and automatically prepends names with the java:comp/env/
prefix.
I am not getting what is meant by global JNDI name? Why does it have to be different across app servers?
I am tagging the question as both EJB2 and EJB 3 since the quote references both the versions. Please feel free to edit if you think otherwise.
A global JNDI name uses a name in the default JNDI context. For example, on WebSphere Application Server, remote EJBs are bound by default to ejb/<app>/<module>/<bean>#<interface>. If you hardcode this lookup string in your application, then the application won't be portable to other application servers (which might use a different scheme for the default name) or even the same WebSphere Application Server if the target application or module name changes.
The solution in EE is for your application to declare an EJB reference, which will be in the java:comp/env context with a name that you choose. When a deployer installs your application on the server, they can bind the java:comp/env name to a global JNDI name that is appropriate for the environment. This same pattern is actually used by all EE resources (data sources, String/int/boolean configuration values, etc.), and when used properly, it is one of the strengths of the EE platform.
I can't tell what the excerpt above is trying to say without more context. Perhaps it's referring to the EJBContext.lookup method, which is effectively a shortcut of doing a lookup relative to java:comp/env.
As a final aside, I'll note that EJB 3.1 defines a standard location of java:global/<app>/<module>/<bean>!<interface> for EJB bindings. Regardless, it is still a best practice to use EJB references when doing lookups across applications (or even across modules if you're not in full control of the application that will contain the EJB client).
Respected EJB Expert,
I am writing this email after lot of R&D. Recently I attended an interview wherea I was asked for EJB event cycle in terms of method invocation. I told them exactly whatever is mentioned at internet. But the interviewer was very dangerously expert. He asked me which component calls which method. Eg. who created the EJB home object and EJB Object.. I answered him with the info what I had... but then he confused me a lot especially by asking me who invokes the above methods in EJB 3.0. Basically he wanted me to tell the complete cycle starting from the client's JNDI lookup till client getting the response of the EJB method. He also wanted to know the enviornment in which the method or event occurs and who invokes the method or event.
I will be very thankful to you if can provide me with your inputs in the below format for all EJBs for 2.0 and 3.0 version
Environment ## Method-name or Event ## Method or Event Invoker
The correct answer is that the EJB container itself is responsible for creating the EJB home implementation, instantiating the EJB object instances, and invoking all lifecycle methods on the EJB object instance.
For EJB 2.x, the client looks up a reference to a home from JNDI, and the container provides an object that implements the home interface. The container home object responds to the create method by returning another container proxy object that implements the component interface, which allows it to implement all the EJB qualities of service (transaction, security, java:comp, etc.) before delegating the actual bean instance that it creates.
For EJB 3.x, the situation is similar, except the container proxy object that implements the business interface is either injected directly or looked up directly from JNDI because the home interface is no longer required.
We all know that in the web tier there is the possibility that only a single instance of a given Servlet exists which services multiple requests. This can lead to threading issues in instance variables.
My question is, is it safe to inject an EJB using the #EJB annotation into a servlet as an instance variable?
My initial instinct would be no, under the assumption that the same instance of the EJB would service multiple requests at the same time. It would seem that this would also be the instinct of a number of other programmers: Don't inject to servlets
However have I jumped to the wrong conclusion. Clearly what is injected into the servlet is a proxy, under the hood does the container actually service each request with a different instance and maintain thread safety? As this forum would suggest: Do inject to servlets
There seems to be a lot of conflicting opinions. WHICH IS CORRECT???
It is safe to inject an EJB in a Servlet as a Servlet instance variable, as long as the EJB is Stateless. You MUST NEVER inject a Stateful Bean in a Servlet.
You must implement your EJB stateless in that it doesn't hold any instance variable which itself holds a stateful value (like Persistence Context). If you need to use the persistence context, then you must get an instance of it IN the methods of the EJB. You can do that by having a PersistenceContextFactory as a EJB instance Variable and then you get an instance of the entity manager from the Factory in the method of the EJB.
The PersistenceContextFactory is thread-safe, thus it can be injected in an instance variable.
As long as you comply to the above mentioned rules, it should be thread-safe to inject a Stateless Bean in a Servlet
Your reference "Don't inject to servlets" mentions nothing about ejbs or #ejb annotation. It talks about not thread safe objects such as PersistenceContext.
Per EJB spec you can access ejbs from variety of remote clients including servlets (EJB 3.0 Specification (JSR-220) - Section 3.1). Injecting ejb using #EJB annotation is a method of obtaining EJB interface via dependency injection (section 3.4.1) which is alternative to looking up ejb objects in the JNDI namespace. So there is nothing special about #EJB annotation with respect to EJBs obtained.
So, based on EJB 3.0 Spec, it's a standard practice to obtain ejbs from servlets using #EJB annotation.
It's a mixed bag.
Stateless session beans may be injected and are safe. This is because even if a single instance of a stub is used, access to the methods will be serialized by the container.
I think what inferreddesign says is not true. It doesn't matter if the stateless session bean uses a persistence context. Only one caller will ever access a single bean instance at the same time, so even though the persistence context is not thread safe, the EJB guards against multiple access to it. Think of it as if every session bean method has the synchronized keyword applied to it.
The main problem with injecting an EJB in a Servlet I think is performance. The single stub instance will become a major area of contention when multiple requests are queuing up while waiting for a session bean method to be executed for them.
I think the simple answer is that you aren't guaranteed that it is safe.
The reason for this is that there is nothing explicit in the EJB specification that says EJB home interfaces have to be thread safe. The spec outlines the behaviour of the server side part only. What you will probably find is that the client skeletons are actually thread safe but you would need to look at how they are implemented by the library you are using. The annotation part will just expand into a service locator so that doesn't buy you anything.