As far as I understand "pre-CDI" EJB and resources injection solutions (#EJB, #Resource and others, to be clear) use the JNDI service to locate objects "known" to the container by virtue of being JNDI registered, and then inject them where requested.
CDI, instead, relies on bean-discovery-mode parameter (ALL or ANNOTATED) to discover beans that need to be managed. But how is this process actually performed? A runtime scan of... what? Is JNDI not involved at all?
I have the feeling I'm getting something wrong about the whole mechanism...
The bean discovery process is described in detail in the CDI specification. Basically, the CDI container scans bean deployment archives for classes with certain annotations.
JNDI is not involved at all. Unlike EJBs, CDI beans cannot be looked up via JNDI in general.
Only the BeanManager itself can be looked up under the name of java:comp/BeanManager, but this is almost never required, unless you need to access managed beans from unmanaged code.
Related
I'm testing my application using junit and OpenEJB container to provide context for my beans. It's finding all beans from classpath and starting them. Unfortunatelly there are some beans I would like to remove from context, so I can replace those beans with other implementations, mocking certain functionalities.
I'm aware of openejb.deployments.classpath.exclude property.
I even tried to use it as follows properties.put("openejb.deployments.classpath.exclude", ".*/CommonCache.*"); as it was sugested in this SO question.
OpenEJB sees this property but bean is still starting as shown in logs below.
Using 'openejb.deployments.classpath.exclude=.*/CommonCacheBean.*'
Auto-deploying ejb CommonCacheBean: EjbDeployment(deployment-id=CommonCacheBean)
Jndi(name="java:global/ejbs/CommonCacheBean!my.package.ICommonCache")
Created Ejb(deployment-id=CommonCacheBean, ejb-name=CommonCacheBean, container=Default Stateless Container)
So there is my question. Is there a way to exclude single bean(s) from OpenEJB context? It doesn't matter to me if it will be achieved this config way or by manual operations in java code.
If anyone is interested i didn't manage to remove beans from context. Although there is an unbind() method in context it does not seem to work on OpenEJB context.
I succeded in replacing beans manually with rebind() but it was too late because they were already injected into another beans.
They way i solved my problem was by using annotaion #Alternative on mock implementation. I also had to add entries in beans.xml to show container those beans and change the way I inject them from #EJB to #Inject.
I'm going through the EJB 3.1 spec and am trying to grasp the different possible ways a JNDI call can be made.
You can do it using a SessionContext and an InitialContext (or a self-created context based on the Initial- or SessionContext).
Based on which you use the syntax differs, but I can't seem to find the logic behind it.
So my question is: when can I use what syntax to use JNDI calls within an EJB container environment?
The rest of this question just serves as illustration of my point.
For example, I believe this is always possible for a correctly injected sessioncontext or created initialcontext:
ctx.lookup(java:global[/<app-name>]/<module-name>/<bean-name>[!<fully-qualified-interface-name>])
ctx.lookup(java:comp/env ...)
// special ones like these
ctx.lookup("java:comp/UserTransaction");
ctx.lookup("java:comp/ORB");
Sometimes (only for session context?) this shorter version is possible:
ctx.lookup(<bean-name>);
What about in an embedded environment, can only global references be used?
I usually inject EJBs inside EJB container with #EJB annotation. So the JDNI look ups are done by the server at deploy time.
For example JBOSS deployment:
INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-2) JNDI bindings for session bean named TestBean in deployment unit subdeployment "MyEJB.jar" of deployment "MyProject.ear" are as follows:
java:global/MyProject/MyEJB/TestBean!my.project.TestBean
java:app/MyEJB/TestEJB!my.project.TestBean
java:module/TestEJB!my.project.TestBean
java:global/MyProject/MyEJB/TestEJB
java:app/MyEJB/TestBean
java:module/TestBean
Some are per EJB specification some are application server dependent.
If you have to make look ups from context I think the best way is to use java:global.
You can also find some additional info at: http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#POJOLocalEJB
jndi is a bit like a file system. You can refer to things using a relative path based on where you are in the tree (where you "cd"-ed to).
The injected session context is by default "positioned" on java:comp, so there you reference things that are available in java:comp, without the need to provide the "full path".
Note that java:comp itself is relative to a single EJB bean, or because of historical reasons to the entire Web module.
I'm not 100% sure what you mean with embedded environment, but if the code from which you are doing the JNDI lookup is not part of any of the predefined scopes (like java:module, java:app, etc) only java:global can be portably used.
I have 2 spring contexts: "webapplication" context and a "core" context. The context "core" is initialized at server startup and attached to a Singleton class that holds the context. The "webapplication" context is initialized when the webapplication is started.
I want to inject bean dependencies from beans in one context to the other (bidirectional access). The webapplication beans are to be "session" scoped beans.
I'm testing this proof of concept with: webapp bean --> (that depends on) core bean --> (that depends on another) webapp bean.
At the webapplication context initialization i could inject "core" beans to the "webapplication" beans (a BeanFactory that acceses the singleton do the magic), but can't figure out how to do the inverse; because the Spring ThreadLocal that holds the WebApplicationContext is not yet initialized.
The question is. Is it what i'm trying to do possible? If the answer is "yes", how would you do that?
Thank's in advance.
EDIT:
I'd realized i'm doing something wrong. The fact is that i'm trying to inject in the service layer a dependency to a session bean, at the wrong time; that is, at the web initialization time when i have no current user session.
This looks to me like an architectural issue, not a technical (and certainly not Spring) one. Your separation between core context and web context is very good. The former handles business processes while the latter is responsible for representation, maybe some API.
The dependency from web (representation, access) to core is understandable and required - after all you are building an interface over business routines. This is how spring-mvc works by default, creating separate child (web) application context of core context.
I can hardly imagine a use case for inverted dependency. Why is your business logic depending on web layer? What if you try to migrate your application one that to a different representation technique (desktop, mobile)? Can you justify the reason for this inverted dependency? What do you mean by session bean?
Bidirectional dependencies, as well as static singletons holding a class-loader wide reference to application context should indicate that something is wrong with the design.
I'm just getting started with JPA, creating stateless session beans from the JPA entities, then accessing the beans through a web service. While I have a lot of experience developing database backed web services "the old way", I have some questions about what's going on behind the scenes with this new "annotation driven approach".
What I see is, NetBeans sort of directs you to build applications in this manner though their wizards.
Create an Enterprise Application with EJB and Web Application modules.
Create Entity classes. I created mine from an existing database.
Create session beans from the entity class.
Create Web services from the session bean.
It all looks pretty simple, but what's going on behind the scenes? Specifically:
I see that the web service (created with the #WebService annotation) references my stateless session bean (using the #EJB reference).
What happens here? Does it just grab an instance of the EJB from the application server's EJB pool?
Nevermind. I was thinking of an instance where there was more than 1 table - meaning more than 1 type of Entity class and more than 1 type of EJB. I was looking at the web service and just seeing the #EJB reference and didn't understand who it was getting the bean type from that annotation. Just below that however, it the reference to the local bean interface - so that's that.
If there is more than 1 type of EJB deployed to the server, how does it know which one to grab?
The EJB is defined via the #Stateless and #Local annotations. The bean implementation references an EnityManager via the #PersistenceContext annotation.
Where is the jndi lookup to the database done (maybe in the persistence.xml file)?
Do all of the EJBs share a common EntityManager (assuming the EntityManager is thread safe)? If not, I know that the EnityManager utilizes a second level cache to help reduce trips to the database, are these caches somehow kept in sync?
I know this is a lot of questions, but they're all sort of related and there seem to be a lot of complicated concepts for something that's so easy to build through the wizards. I want to make sure I understand what's all going on here.
Thanks in advance!
What happens here? Does it just grab an instance of the EJB from the application server's EJB pool?
A JAX-WS web component endpoint (as opposed to a JAX-WS EJB endpoint) follows the typical servlet threading model, which means that typically there is one instance that is executed concurrently for each client. JAX-WS implementations are free to leverage pools of bean instances to handle a request in a fashion similar to stateless session EJB components. (source: Developing Applications for the JavaTM EE Platform FJ-310).
In all cases, it is fine to inject/look-up stateless beans because the container guarantees that the beans will always be thread safe. In affect, the container automatically serializes clients calls but uses instance pooling to make sure you still get concurrency benefits.
If there is more than 1 EJB deployed to the server, how does it know which one to grab?
Hmm... I didn't get this one. Can you clarify what you mean exactly? Why would there be any ambiguity?
Where is the jndi lookup to the database done (maybe in the persistence.xml file)?
In a Java EE environment, you specify your data source in a <jta-data-source> element in each persistence unit of the persistence.xml file (which can contain several persistence units) and the data source will be obtained by the EntityManager (only when needed, i.e. only if a data access is really needed).
Do all of the EJBs share a common EntityManager?
No. The EntityManager is a non-thread-safe object that should be used once, for a single business process, a single unit of work, and then discarded. In a Java EE environment using EJB 3, the default pattern is "entitymanager-per-request". A request from the client is send to the EJB 3 persistence layer, a new EntityManager is opened, and all database operations are executed in this unit of work. Once the work has been completed (and the response for the client has been prepared), the persistence context is flushed and closed, as well as the entity manager object. (source: Chapter 4. Transactions and Concurrency).
I want to use an EJB3 from within my Tapestry Page class, I can do JNDI lookup for it, but it will me much convenient to use EJB injection or Tapestry IoC. Is that possible?
Of course! You can either contribute your EJBs via Tapestry's IOC container, so you would do the JNDI lookup in your build methods instead of all over your code (see the manual for information).
Or you could wire up your EJBs as Spring beans (see the Spring EJB documentation for details), and use Tapestry-Spring to allow injecting them into your components via #Inject.