I'm currently migrating a JBoss service class from AS5.1 to AS6 (not going to AS7 for a variety of reasons).
For AS5.1, the service implements a {serviceName}MBean and has a jboss-service.xml with attribute values. It's packaged in a jboss-sar, which is packaged in an EAR to be deployed. When deployed, the service fields are populated with the values from jboss-service.xml, and the service is automatically registered into JMX.
I would like to achieve the same thing using AS6, but would like the service to support CDI - so I'd like its new #Inject injection points to be satisfied. I need these to be satisfied in the object registered with JMX, so that methods called via JMX can reference injected fields, but I'm struggling to achieve this.
I've had to package the service in a jar, instead of a jboss-sar, for classloader reasons, but let's say it's otherwise unchanged. When deployed to AS6, all works as before - service goes into JMX, values from XML propagate to the object. However, the instance created does not have its CDI injection points satisfied, and neither does the object registered in JMX.
If I annotate the service class with #Startup and #javax.ejb.Singleton, but keep its interface and the jboss-service.xml, the object registered into JMX still does not have its CDI injection points satisfied. However if I programmattically deregister that bean, and re-register the instance in a #PostConstruct method, then the bean in JMX DOES have its injection points satisfied. However that bean no longer has the values specified in the jboss-service.xml.
So how can I get the best of both worlds? CDI and the usual JBoss service behaviour? What is the correct way to implement a JBoss service with CDI? I've been unable to find documentation on this. Hope someone can help.
Thanks,
Ben
As a worst-case fallback, you should be able to use the CDI extension API to get your service to be injected. I don't think you would need to write a fully-fledged extension, but if you have an initialisation hook in the service object, you can do this (lifted with minor editing from the docs, not compiled or tested):
public static <T> void inject(T object) {
BeanManager beanManager = (BeanManager)new InitialContext().lookup("java:comp/BeanManager");
AnnotatedType<T> type = beanManager.createAnnotatedType(object.getClass());
InjectionTarget<T> it = beanManager.createInjectionTarget(type);
CreationalContext ctx = beanManager.createCreationalContext(null);
it.inject(object, ctx);
it.postConstruct(object);
}
Basically, any object to that method will get injected. All the usual CDI annotations should work. Hopefully.
As mentioned in the comments above, it seems Tom's right - there's no 'nice' way of created a CDIed, JMX bean in one go, you either have to put your JMX bean in CDI, as is suggested above, or put you CDIed bean into JMX. We tried the former, but it appears the BeanManager isn't bound to JNDI at the point the service starts up.
So instead we went with CDI bean -> JMX. We're creating the services as Singleton EJBs, so their injection points are satisfied, and they then get registered/unregistered to JMX in their PostConstruct/PreDestroy methods, using German Escobar's excellent CDI portable extension (germanescobar.net/2010/01/cdi-portable-extension-jmx.html, community.jboss.org/thread/148750 is also helpful).
May try to use ApplicationScoped beans and get them to start by observing a ContainerInitialized(?) event, however, as we don't need all the features of an EJB. Haven't tried that yet, mind...
Related
I feel there is a little mess in the Java EE 6 spec. There are several sets of annotations.
We have javax.ejb annotations like #Stateful and #Stateless for creating EJBs.
There is also a #javax.annotation.ManagedBean to create a managed bean.
There are annotations in javax.enterprise.context like #SessionScoped and #RequestScoped.
What is more there are also #ManagedBean and #SessionScoped/#RequestScoped annotations in javax.faces.bean package.
And to make things event more complicated there is a package javax.inject with #Named annotation.
Can someone please describe how they are related one to another?
Where can I use #EJB, #Inject or #ManagedPropery to inject other beans?
First of all let me do some clarifications:
Managed bean definition : generally a managed bean is an object that its life cycle (construction, destruction, etc) is managed by a container.
In Java ee we have many containers that manage life cycle of their objects, like JSF container, EJB container, CDI container, Servlet container, etc.
All of these containers work kind of independent, they boot in application server initialization and scan classes of all artifacts including jar, ejb-jar, war and ear files in deployment time and gather and store some metadata about them, then when you need an object of a class at runtime they will give you instances of those classes and after finishing the job, they will destroy them.
So we can say that we have:
JSF managed beans
CDI managed beans
EJB managed beans
And even Servlets are managed beans because they are instantiated and destroyed by a container, which is a servlet container.
So when you see the Managed Bean word, you should ask about the context or type of it.(JSF, CDI, EJB, etc.)
Then you might ask why we have many of these containers: AFAIK, Java EE guys wanted to have a dependency injection framework, but they could not gather all requirements in one specification because they could not predict the future requirements and they made EJB 1.0 and then 2.0 and then 3.0 and now 3.1 but EJB's target was for just some requirements (transaction, distributed component model, etc).
At the same time (in parallel) they realized that they need to support JSF too, then they made JSF managed beans and another container for JSF beans and they considered it a mature DI container, but still it was not complete and mature container.
After that Gavin King and some other nice guys ;) made CDI which is the most mature DI container I've seen. CDI (inspired by Seam2, Guice and Spring) was made to fill the gap between JSF and EJB and lots of other useful stuff like pojo injection, producer methods, interceptors, decorators, integration SPI, very flexible, etc. and it can even do what EJB and JSF managed beans are doing then we can have just one mature and powerful DI container. But for some backward compatibility and political reasons Java EE guys want to keep them!!!
Here you can find the difference and use cases for each of these types:
JSF Managed Beans, CDI Beans and EJBs
JSF was initially developed with its own managed bean and dependency injection mechanism which was enhanced for JSF 2.0 to include annotation based beans. When CDI was released with Java EE 6, it was regarded as the managed bean framework for that platform and of course, EJBs outdated them all having been around for well over a decade.
The problem of course is knowing which one to use and when use them.
Let’s start with the simplest, JSF Managed beans.
JSF Managed Beans
In short, don’t use them if you are developing for Java EE 6 and using CDI. They provide a simple mechanism for dependency injection and defining backing beans for web pages, but they are far less powerful than CDI beans.
They can be defined using the #javax.faces.bean.ManagedBean annotation which takes an optional name parameter. This name can be used to reference the bean from JSF pages.
Scope can be applied to the bean using one of the different scopes defined in the javax.faces.bean package which include the request, session, application, view and custom scopes.
#ManagedBean(name="someBean")
#RequestScoped
public class SomeBean {
....
....
}
JSF beans cannot be mixed with other kinds of beans without some kind of manual coding.
CDI Beans
CDI is the bean management and dependency injection framework that was released as part of Java EE 6 and it includes a complete, comprehensive managed bean facility. CDI beans are far more advanced and flexible than simple JSF managed beans. They can make use of interceptors, conversation scope, Events, type safe injection, decorators, stereotypes and producer methods.
To deploy CDI beans, you must place a file called beans.xml in a META-INF folder on the classpath. Once you do this, then every bean in the package becomes a CDI bean. There are a lot of features in CDI, too many to cover here, but as a quick reference for JSF-like features, you can define the scope of the CDI bean using one of the scopes defined in the javax.enterprise.context package (namely, request, conversation, session and application scopes). If you want to use the CDI bean from a JSF page, you can give it a name using the javax.inject.Named annotation. To inject a bean into another bean, you annotate the field with javax.inject.Inject annotation.
#Named("someBean")
#RequestScoped
public class SomeBean {
#Inject
private SomeService someService;
}
Automatic injection like that defined above can be controlled through the use of Qualifiers that can help match the specific class that you want injected. If you have multiple payment types, you might add a qualifier for whether it is asynchronous or not. While you can use the #Named annotation as a qualifier, you shouldn’t as it is provided for exposing the beans in EL.
CDI handles the injection of beans with mismatched scopes through the use of proxies. Because of this you can inject a request scoped bean into a session scoped bean and the reference will still be valid on each request because for each request, the proxy re-connects to a live instance of the request scoped bean.
CDI also has support for interceptors, events, the new conversation scope and many other features which makes it a much better choice over JSF managed beans.
EJB
EJBs predate CDI beans and are in someways similar to CDI beans and in other ways very different. Primarily, the differences between CDI beans and EJBs is that EJBs are :
Transactional
Remote or local
Able to passivate stateful beans freeing up resources
Able to make use of timers
Can be asynchronous
The two types of EJBs are called stateless and stateful. Stateless EJBs can be thought of as thread safe single-use beans that don’t maintain any state between two web requests. Stateful EJBs do hold state and can be created and sit around for as long as they are needed until they are disposed of.
Defining an EJB is simple, you just add either a javax.ejb.Stateless or javax.ejb.Stateful annotation to the class.
#Stateless
public class BookingService {
public String makeReservation(Item Item, Customer customer) {
...
...
}
}
Stateless beans must have a dependent scope while a stateful session bean can have any scope. By default they are transactional, but you can use the transaction attribute annotation.
While EJBs and CDI beans are very different in terms of features, writing the code to integrate them is very similar since CDI beans can be injected into EJBs and EJBs can be injected into CDI beans. There is no need to make any distinction when injecting one into the other. Again, the different scopes are handled by CDI through the use of proxying. One exception to this is that CDI does not support the injection of remote EJBs but that can be implemented by writing a simple producer method for it.
The javax.inject.Named annotation as well as any Qualifiers can be used on an EJB to match it to an injection point.
When to use which bean
How do you know when to use which bean? Simple.
Never use JSF managed beans unless you are working in a servlet container and don’t want to try and get CDI working in Tomcat (although there are some Maven archetypes for that so there’s no excuse).
In general, you should use CDI beans unless you need the advanced functionality available in the EJBs such as transactional functions. You can write your own interceptor to make CDI beans transactional, but for now, it's simpler to use an EJB until CDI gets transactional CDI beans which is just around the corner. If you are stuck in a servlet container and are using CDI, then either hand written transactions or your own transaction interceptor is the only option without EJBs.
If you need to use #ViewScoped in CDI you should
use seam-faces or MyFaces CODI module. just add one of them to your classpath and #ViewScoped will work in CDI. MyFaces CODI has an even more solid support of #ViewScoped
use MyFaces CODI's #ViewAccessScoped, it is an extension written on top of CDI by Apache, just download it and use #ViewAccessScoped annotation instead of #ViewScoped.
Use CDI #ConversationScoped and make it long running. See here for more info.
Use Omnifaces #ViewScoped annotation
Some parts pilfered from here.
Yep, this can be confusing.
For some ehm historical reasons JSF and CDI are using the same annotations for scopes, but from different packages.
As you are probably guessing those from javax.faces.bean are from the JSF spec, and are not related to CDI. Do not use them unless you have a very good reason to do so. And do never ever mix them with CDI annotations from javax.ejb. This will produce a sheer endless lists of bugs and subtle anomalies.
I generally recommend that you skim the first few (or even more) pages of the excellent Weld documentation. This should put you on track for Java EE 6.
And feel free to post further questions here.
Since there are no replies specifically about #javax.annotation.ManagedBean, here's a link to the answer of a similar question: Backing beans (#ManagedBean) or CDI Beans (#Named)?. The spec can be found at http://download.oracle.com/otndocs/jcp/managed_beans-1.0-fr-eval-oth-JSpec/. So it looks to me that #javax.annotation.ManagedBean was meant to be a generalization of #javax.faces.bean.ManagedBean.
From what I gathered, JSF Managed Beans are being phased out in favour of CDI Beans (maybe getting deprecated from JSF 2.3?), so I guess #javax.annotation.ManagedBean is all the more becoming obsolete now.
I'm trying to add a Interceptor in a EJB at runtime programmatically via CDI extensions.
This EJB exposes a Remote interface for remote calls. But I'm trying to add this Interceptor in the implementation class of this EJB adding the #Interceptors annontation like in this other SO question (CDI Extensions - Add Interceptors in ProcessAnnotatedType phase)
I think the CDI Extension only executes after the EJB are already registered because the Interceptor is never called.
But, for test purpose I have successfully register and execute an Interceptor programmatically in a simple CDI Bean.
The problem is when I'm try to register in a EJB.
Am I missing something?
Edit:
I'm using Wildfly 8
I think the key problem here is the difference between #Interceptors (EJB ones) and #Interceptor (CDI ones). CDI does not govern EJB container hence adding the EJB annotation (#Interceptors) in CDI extension won't necessarrily kick EJB logic into effect - EJB container might have started at that moment and it won't know of the annotation. Furthermore the CDI extension would add this annotation to the AnnotatedType which is a structure EJB probably won't make use of. On the other hand, all this really depends on the application server as it is responsible for CDI/EJB integration hence as a "bonus" the behavior might differ between AS.
CDI extension is something which allows you to hook into CDI bootstrap lifecycle, therefore you are able to use/enable/add CDI interceptors. I would try going that way instead. BTW even the SO question you referred to speaks of beans.xml/#Priority for enablement which means it uses CDI interceptors and not EJB ones.
Also, an EJB bean should automatically become CDI bean therefore you can attach CDI interceptor to it without changing the bean itself.
I feel there is a little mess in the Java EE 6 spec. There are several sets of annotations.
We have javax.ejb annotations like #Stateful and #Stateless for creating EJBs.
There is also a #javax.annotation.ManagedBean to create a managed bean.
There are annotations in javax.enterprise.context like #SessionScoped and #RequestScoped.
What is more there are also #ManagedBean and #SessionScoped/#RequestScoped annotations in javax.faces.bean package.
And to make things event more complicated there is a package javax.inject with #Named annotation.
Can someone please describe how they are related one to another?
Where can I use #EJB, #Inject or #ManagedPropery to inject other beans?
First of all let me do some clarifications:
Managed bean definition : generally a managed bean is an object that its life cycle (construction, destruction, etc) is managed by a container.
In Java ee we have many containers that manage life cycle of their objects, like JSF container, EJB container, CDI container, Servlet container, etc.
All of these containers work kind of independent, they boot in application server initialization and scan classes of all artifacts including jar, ejb-jar, war and ear files in deployment time and gather and store some metadata about them, then when you need an object of a class at runtime they will give you instances of those classes and after finishing the job, they will destroy them.
So we can say that we have:
JSF managed beans
CDI managed beans
EJB managed beans
And even Servlets are managed beans because they are instantiated and destroyed by a container, which is a servlet container.
So when you see the Managed Bean word, you should ask about the context or type of it.(JSF, CDI, EJB, etc.)
Then you might ask why we have many of these containers: AFAIK, Java EE guys wanted to have a dependency injection framework, but they could not gather all requirements in one specification because they could not predict the future requirements and they made EJB 1.0 and then 2.0 and then 3.0 and now 3.1 but EJB's target was for just some requirements (transaction, distributed component model, etc).
At the same time (in parallel) they realized that they need to support JSF too, then they made JSF managed beans and another container for JSF beans and they considered it a mature DI container, but still it was not complete and mature container.
After that Gavin King and some other nice guys ;) made CDI which is the most mature DI container I've seen. CDI (inspired by Seam2, Guice and Spring) was made to fill the gap between JSF and EJB and lots of other useful stuff like pojo injection, producer methods, interceptors, decorators, integration SPI, very flexible, etc. and it can even do what EJB and JSF managed beans are doing then we can have just one mature and powerful DI container. But for some backward compatibility and political reasons Java EE guys want to keep them!!!
Here you can find the difference and use cases for each of these types:
JSF Managed Beans, CDI Beans and EJBs
JSF was initially developed with its own managed bean and dependency injection mechanism which was enhanced for JSF 2.0 to include annotation based beans. When CDI was released with Java EE 6, it was regarded as the managed bean framework for that platform and of course, EJBs outdated them all having been around for well over a decade.
The problem of course is knowing which one to use and when use them.
Let’s start with the simplest, JSF Managed beans.
JSF Managed Beans
In short, don’t use them if you are developing for Java EE 6 and using CDI. They provide a simple mechanism for dependency injection and defining backing beans for web pages, but they are far less powerful than CDI beans.
They can be defined using the #javax.faces.bean.ManagedBean annotation which takes an optional name parameter. This name can be used to reference the bean from JSF pages.
Scope can be applied to the bean using one of the different scopes defined in the javax.faces.bean package which include the request, session, application, view and custom scopes.
#ManagedBean(name="someBean")
#RequestScoped
public class SomeBean {
....
....
}
JSF beans cannot be mixed with other kinds of beans without some kind of manual coding.
CDI Beans
CDI is the bean management and dependency injection framework that was released as part of Java EE 6 and it includes a complete, comprehensive managed bean facility. CDI beans are far more advanced and flexible than simple JSF managed beans. They can make use of interceptors, conversation scope, Events, type safe injection, decorators, stereotypes and producer methods.
To deploy CDI beans, you must place a file called beans.xml in a META-INF folder on the classpath. Once you do this, then every bean in the package becomes a CDI bean. There are a lot of features in CDI, too many to cover here, but as a quick reference for JSF-like features, you can define the scope of the CDI bean using one of the scopes defined in the javax.enterprise.context package (namely, request, conversation, session and application scopes). If you want to use the CDI bean from a JSF page, you can give it a name using the javax.inject.Named annotation. To inject a bean into another bean, you annotate the field with javax.inject.Inject annotation.
#Named("someBean")
#RequestScoped
public class SomeBean {
#Inject
private SomeService someService;
}
Automatic injection like that defined above can be controlled through the use of Qualifiers that can help match the specific class that you want injected. If you have multiple payment types, you might add a qualifier for whether it is asynchronous or not. While you can use the #Named annotation as a qualifier, you shouldn’t as it is provided for exposing the beans in EL.
CDI handles the injection of beans with mismatched scopes through the use of proxies. Because of this you can inject a request scoped bean into a session scoped bean and the reference will still be valid on each request because for each request, the proxy re-connects to a live instance of the request scoped bean.
CDI also has support for interceptors, events, the new conversation scope and many other features which makes it a much better choice over JSF managed beans.
EJB
EJBs predate CDI beans and are in someways similar to CDI beans and in other ways very different. Primarily, the differences between CDI beans and EJBs is that EJBs are :
Transactional
Remote or local
Able to passivate stateful beans freeing up resources
Able to make use of timers
Can be asynchronous
The two types of EJBs are called stateless and stateful. Stateless EJBs can be thought of as thread safe single-use beans that don’t maintain any state between two web requests. Stateful EJBs do hold state and can be created and sit around for as long as they are needed until they are disposed of.
Defining an EJB is simple, you just add either a javax.ejb.Stateless or javax.ejb.Stateful annotation to the class.
#Stateless
public class BookingService {
public String makeReservation(Item Item, Customer customer) {
...
...
}
}
Stateless beans must have a dependent scope while a stateful session bean can have any scope. By default they are transactional, but you can use the transaction attribute annotation.
While EJBs and CDI beans are very different in terms of features, writing the code to integrate them is very similar since CDI beans can be injected into EJBs and EJBs can be injected into CDI beans. There is no need to make any distinction when injecting one into the other. Again, the different scopes are handled by CDI through the use of proxying. One exception to this is that CDI does not support the injection of remote EJBs but that can be implemented by writing a simple producer method for it.
The javax.inject.Named annotation as well as any Qualifiers can be used on an EJB to match it to an injection point.
When to use which bean
How do you know when to use which bean? Simple.
Never use JSF managed beans unless you are working in a servlet container and don’t want to try and get CDI working in Tomcat (although there are some Maven archetypes for that so there’s no excuse).
In general, you should use CDI beans unless you need the advanced functionality available in the EJBs such as transactional functions. You can write your own interceptor to make CDI beans transactional, but for now, it's simpler to use an EJB until CDI gets transactional CDI beans which is just around the corner. If you are stuck in a servlet container and are using CDI, then either hand written transactions or your own transaction interceptor is the only option without EJBs.
If you need to use #ViewScoped in CDI you should
use seam-faces or MyFaces CODI module. just add one of them to your classpath and #ViewScoped will work in CDI. MyFaces CODI has an even more solid support of #ViewScoped
use MyFaces CODI's #ViewAccessScoped, it is an extension written on top of CDI by Apache, just download it and use #ViewAccessScoped annotation instead of #ViewScoped.
Use CDI #ConversationScoped and make it long running. See here for more info.
Use Omnifaces #ViewScoped annotation
Some parts pilfered from here.
Yep, this can be confusing.
For some ehm historical reasons JSF and CDI are using the same annotations for scopes, but from different packages.
As you are probably guessing those from javax.faces.bean are from the JSF spec, and are not related to CDI. Do not use them unless you have a very good reason to do so. And do never ever mix them with CDI annotations from javax.ejb. This will produce a sheer endless lists of bugs and subtle anomalies.
I generally recommend that you skim the first few (or even more) pages of the excellent Weld documentation. This should put you on track for Java EE 6.
And feel free to post further questions here.
Since there are no replies specifically about #javax.annotation.ManagedBean, here's a link to the answer of a similar question: Backing beans (#ManagedBean) or CDI Beans (#Named)?. The spec can be found at http://download.oracle.com/otndocs/jcp/managed_beans-1.0-fr-eval-oth-JSpec/. So it looks to me that #javax.annotation.ManagedBean was meant to be a generalization of #javax.faces.bean.ManagedBean.
From what I gathered, JSF Managed Beans are being phased out in favour of CDI Beans (maybe getting deprecated from JSF 2.3?), so I guess #javax.annotation.ManagedBean is all the more becoming obsolete now.
Not terribly experienced using EJB, and I ran into the following problem with which I hope one of you guys can help out.
Suppose the following situation: a set of #Local beans have been defined to provide access to a database. These beans are very simple, and are deployed on application server A (Weblogic 10.3.3). We want to provide access to these local beans via remote, and since we already have a "services" module set-up for providing external access to our services, our idea was to create a new #Remote service that uses the local beans described above (injected via #EJB). These service beans are also deployed on application server A. For example:
#Local
public interface DatabaseBeanLocal { doStuff(); }
#Stateless(name = "ejb/DatabaseBean", mappedName = "DatabaseBean")
public class DatabaseBean implements DatabaseBeanLocal { doStuff() { ... } ; }
#Remote
public interface ServiceBean { doSomeOtherStuff(); }
#Stateless
public class ServiceBeanImpl implements ServiceBean
{
#EJB(name = "ejb/DatabaseBean", mappedName = "DatabaseBean")
private DatabaseBeanLocal myDatabaseBean;
... methods etc. ...
}
The client that will actually use these remote beans is actually run on a different application server; application server B (also Weblogic 10.3.3). When we look-up the ServiceBean bean from our client, that works fine. When we call a method on it that needs access to DatabaseBean however, the call fails. The Weblogic server says it cannot find a bean for the DatabaseBean interface.
My questions: is this set-up even possible? In other words: will Weblogic (or another container) inject the local bean into the remote bean so that the client gets an instance of the remote bean that is capable of calling actions on the local bean (I assume not, but I'm asking anyway to be sure)?
If not, the I guess we'll have no other choice than to skip the service layer and provide direct access to the DatabaseBean example above via #Remote.
Update 1
After doing some tests, simply defining DatabaseBean above as #Remote rather than #Local "fixes" this issue. Ofcourse, this is not really a fix since this will call the DatabaseBean remotely, which is ridiculous because it's in the same module as the service. I'm starting to suspect that wrapping a local EJB with a remote EJB is simply not possible.
Update 2
What we've found so far:
We've not been able to manually inject the local EJB so far, because we cannot actually find it at runtime.
Weblogic apparently does not include local EJBs in the JNDI tree.
Calling the ServiceBean from outside the AS on which it is deployed still does not work, because the dependency on the local EJB is never resolved, or resolved client-side which means it's not found.
Local means local to EAR not to AS.
Your local and remote Beans must be in same EAR (not only in same AS). Are they?
-- edit --
Hmm.. If they're in the same EAR then it should work. I.e. answer to your question "is such a setup even possible?" is Yes.
Unfortunately now we're talking abt pure and simple debugging. First thing I would do is try and check if teh local bean (DatabaseBean I guess) is actually registered and working using WebPhere UTC equivalent in WebLogic (I never worked in WebLogic). I can list a 100 other things you can check for more logs/traces/symptoms but well, that's the way debugging goes.
Managed to get this issue resolved. the following configuration works for Weblogic 10.3.3 and allows for a remote EJB to use a local EJB, where the remote EJB can be called from anywhere.
Ultimately — after a lot of testing — the trick was apparently specifying a beanName value for the #EJB annotation used to mark the local bean as a dependency of the remote bean. Doh!
Deployment
#Local EJB is deployed on AS-A in EAR-1 (in its own module/JAR)
#Remote EJB is deployed on AS-A in EAR-1 (in its own module/JAR)
Client code that calls the remote service is deployed on AS-B in its own EAR archive
Annotations
The local EJB is a very simple and straightforward EJB bean, with the following interface and implementation:
#Local
public interface LocalBeanLocal {
// Implementation omitted
}
#Stateless(name = "LocalBean")
public class LocalBean implements LocalBeanLocal {
// Implementation omitted
}
The remote EJB is again a relatively simple EJB bean, except that it has a dependency on LocalBean. This dependency is expressed through the #EJB annotation; but it would seem that the beanName attribute is required for Weblogic to resolve this dependency correctly. Without the beanName attribute, calling the remote EJB would not work for us (in the sense that there would always be some kind of error when the local bean was involved)!
#Remote
public interface RemoteBeanRemote {
// Implementation omitted
}
#Stateless(name = "RemoteBean")
public class RemoteBean implements RemoteBeanRemote {
#EJB(beanName = "LocalBean")
private LocalBeanLocal localBean;
// Implementation omitted
}
What is apparently important here is that the beanName attribute in the remote service dependency declaration (#EJB(beanName = "LocalBean")) should have the same value as the bean name defined in the local bean implementation (#Stateless(name = "LocalBean")).
Lookup
Getting a reference to your remote EJB is done the traditional way, there doesn't seem to be a specific requirement. In our case, we look-up the remote service via JNDI.
I have been working through this tutorial. Halfway though it creates an interface and facades for an EJB. Can anyone tell me when I reference the interface using the #EJB annotation, where does it actually make the link between the interface and the actual enterprise java bean itself.
Thanks for the help.
~ Kyle.
It is AFAIK not mandated by the J2EE specification how this is actually solved or implemented by the application server. The most common solution is that the app server uses its own mapping between bean class names and JNDI names, so that depending on the bean class name, it is bound to a specific JNDI path when deploying the application and the same class name -> JNDI path conversion is used for injecting the EJB reference on the "client side".
It will be done inside the EJB container.
When you add this annotation, you'll actually be telling the IoC container of your application server which implementation of the given EJB you want.