EJB cannot inject other EJB - java

I do have a EJB ActionService which I can inject into other EJBs, that is working fine.
Now I created another EJB:
#Stateless
public class ActionsPerDateDataSet extends ScriptedDataSetEventAdapter {
#EJB
ActionService actionService;
#Override
public void open(IDataSetInstance dataSet) {
actionService.foo() // However actionService is null here!
}
}
Where the ScriptedDataSetEventAdapter comes from another framework (BIRT).
However now my actionService is always null. I can not understand why

You should introduce the lib as ejbModule in ear file , so that container search the jar file and deploy it and inject it whenever it needs

ActionService has an interface with the #local annotation or if this is a class it has to have the annotation #LocalBean.
(this to be able to access the instance of it at runtime)
In case it is an interface and if it has multiple implementations you will have to reference the implementation you need using #EJB (beanName = "nameOfImplementation") in case it is a class where #LocalBean is used to use #EJB (name = "nameEjb")
Interface with #Local
Class with #LocalBean
In the aggregation class
Interface with multiple implementations #EJB(beanName="nameOfImplementation")
Class #EJB(name="nameEjb")
note: implements an interface for ActionService with #Local and test
note: add trace the console log to know if the class is being initialized as an ejb:ActionService

Did you try using CDI? I think it is worth a shot. You need to place an empty beans.xml inside your meta-inf folder and change #EJB to #Inject. But the only way this could work is if you have the external lib and your war/jar file in the same deployment unit.
if this does not work you will need to use JNDI for looking up your bean:
http://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html

It is possible that the class ScriptedDataSetEventAdapter
can not be initialized in the EJB Container (First part of the cycle)
and as the initialization is not correct, the dependency injection (#EJB and #Inject) is not made.
What you could do is change the Design of your EJB and instead it's extends "ScriptedDataSetEventAdapter"
change it to a composition.
#Stateless
public class ActionsPerDateDataSet {
ScriptedDataSetEventAdapter scriptedDataSetEventAdapter;
#EJB
ActionService actionService;
#PostConstruct
public void init (){
try {
scriptedDataSetEventAdapter = new ScriptedDataSetEventAdapter();
} catch( AppException e){
}
}
#Override
public void open(IDataSetInstance dataSet) {
actionService.foo() // However actionService is null here!
}
}

Related

#Inject annotation not working

I'm trying to use CDI for the first time. While I have successfully injected one EJB inside another using #EJB, I can't get the #Inject annotation to work.
#Stateless
public class AccountDaoImpl implements AccountDAO {
#Inject
private MultiTenantEntityManagerImpl mtem; //always null
}
And the multi-tenancy entity manager looks like this:
#Default
public class MultiTenantEntityManagerImpl {
.....
}
I've created a beans.xml file (empty) but and shoehorned it into the META-INF folder in the built jar file. Still no joy.
I'm sure it's something simple. I'm running in jboss 5.0.1.GA.
Update
So it looks like the #Inject annotation is not supported in jboss 5.
An alternative is to use the #EJB annotation, but this isn't working either:
#Stateless
public class AccountDaoImpl implements AccountDAO {
#EJB
private MultiTenantEntityManager mtem; //still null!
}
Weirdly, in another EJB, this exact declaration of the entity manager is working fine.
in my case i was missing subsystem in the standalone
It looks like, in jboss 5 at least, an #EJB annotation will only be respected if both the following conditions hold:
The class in which you're using it is an EJB
The class is retrieved from the container somehow (eg JNDI), rather than being simply instantiated via a constructor.

EJB injection into non managed objects

we are upgrading our web application to Oracle WebLogic 12c with EJB 3.x, and we got an issue.
This is the scenario...
We have a simple EJBs that we are going to call MyService, defined with its bean and local/remote interfaces defined by the EJB 3.x annotations.
Here is a pseudo code of the scenario:
class MyListener implements ServletContextListener {
#EJB private MyService myService;
public void contextInitialized(ServletContextEvent arg0) {
// Here myService is correctly instantiated, so we do something...
}
}
Now we have to move the contextInitialized method logic inside an utility class, so the new scenario will be:
class MyUtility {
#EJB private MyService myService;
public void doSomething() {
// Here myService is NULL!!!!!
}
}
class MyListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent arg0) {
new MyUtility().doSomething();
}
}
I have read a lot of documentation about that problem, and I discovered that only some kind of classes are scanned by the Application Server to resolve the injected EJBs ( Java EE 6, 5, 7 | List of managed beans or classes: EJBs , JSF beans and ..? ).
Is there a workaround to force the scanning of a custom class like mine with WebLogic?
Thank you very much.
There is an option to wrap you Injection into a CDI-Component and to use this one in your code. CDI has the capability to work in standalone java, as soon as you configured it well.
Another helpful option can be the fact, that CDI supports EJB-injection too (in some usecases):
CDI.current().select(MyService.class).get();
BUT: EJBs has their own Transaction-Management. So I would prefer the wrapping into a cdi-component to get more controll in it.

Demistifying EJB annotations and injection

I'm currently puzzled with the way Glassfish 3.1.2.2 handles EJBs.
I have an OSGi project, which consists of many OSGi bundles (jars). Also, there are a few WARs, including a Tapestry web application.
In one such bundle, let's call it "interfaces.jar", I have an interface defined:
public interface MyInterface() {
public static final String JNDI_NAME = "java:global/MyInterface";
void myMethod();
}
The implementation of that interface is as following, and it's contained in bundle "beans.jar":
#Stateless
#EJB(name = MyInterface.JNDI_NAME, beanInterface = MyInterface)
public class MyBean implements MyInterface() {
void myMethod() {
...
}
}
I am calling it from my Tapestry WAR app via JNDI lookup:
InitialContext.doLookup(MyInterface.JNDI_NAME);
Now, I was reading EJB 3.1 specification, and it says that I can one of the following scenarios:
Interface has #Local annotation; EJB is implementing this interface.
Interface is a plain Java interface without annotation; EJB with #Local annotation is implementing it.
Interface is a plain Java interface without annotation; EJB is implementing it.
Interface is a plain Java interface without annotation; EJB with #Local annotation is not implementing it.
EJB doesn’t have any special annotations.
So, by elimination:
I don't have #Local on interface
I don't have #Local on EJB
Seems somewhat right
I don't have #Local on EJB
I have #EJB annotation on my EJB
So, it seems that it's case 3:
"Because it’s the only implemented interface of the EJB, a container assumes that it must be a local business interface."
Now, a few questions:
Is my interface a local or remote one, since there is no local or remote annotation?
If it is local, I should be able to inject it with #EJB annotation, but it fails?
If it's remote, it is not in compliance with the explanation a few lines above?
If I add either #Local or #Remote, and perform JNDI lookup, I get a naming exception and NPE telling me there is nothing under that JNDI_NAME. How is that possible?
What exactly does #EJB(name = ..., beanInterface = ...) do on bean class and how does it interact with #Local and #Remote annotations?
1.)
First, let's see your example without the "unnecessary" #EJB annotation
#Stateless
public class MyBean implements MyInterface() {
void myMethod() {
...
}
}
You can now see clearly, that the EJB implements only one interface. As you mentioned in the 3rd points, "Interface is a plain Java interface without annotation; EJB is implementing it.", so MyInterface is a Local Business Interface of the MyBean EJB.
2.)
You use wrong JNDI name for the lookup:
#Stateless
public class MyBean implements MyInterface() {
...
The global JNDI name of your EJB:
java:global[/app-name][/module-name]/MyBean[!interface-name]
The interface-name is "MyInterface", but it is optional if there are no other business interfaces for your beans, like here, so you can skip it.
You have to figure out what the application- and module-name is for your bean in case of OSGI.
In a simple EJB application, the application-name is the name of the .ear file, and the module-name is the name of the .war/.jar file. application-name can be skipped if your module is not packaged in an ear.
So for example:
new InitialContext().lookup("java:global/myModuleName/MyBean");
5.)
#Stateless
#EJB(name = "MyInterface", beanInterface = MyInterface.class)
public class MyBean implements MyInterface() {
void myMethod() {
...
}
}
Here the #EJB annotation creates an EJB and put a reference to it into the Environment Naming Context (ENC). So it does nothing with the MyBean EJB, just expand its ENC with a new entry.
So from the business method of the current bean you can lookup for that new entry:
void myMethod() {
new InitialContext().lookup("java:comp/env/MyInterface")
}
You can locate the bean's ENC by "java:comp/env/" JNDI name.
As you can see, the name parameter defines the name of the entry in the ENC.
The beanInterface defines the Business Interface of the created Bean. If the Bean has more business interfaces, then you have to define beanName too, so the container could determine wich Bean you would like to create.
You can read about this topic here:http://thegreyblog.blogspot.hu/2010/09/introduction-to-ejb-30-injection-and.html

can both "LocalBean" and "Remote" be annotated on one bean?

I know it might sound elementary, but i'm wondering the following singleton bean:
#Startup
#Singleton
#LocalBean
public class MyServiceBean {
public String sayHello() { return "Hello"; }
}
Now i think "remote" clients might need use this bean, so I want to add a Remote interface to this bean:
#Remote
public interface MyService {
String sayHello();
}
Can I just make my bean implements the new remote interface?
If "MyServiceBean" implements the "MyService" remote interface, it will become a bean with a "remote-interface-view" ... but after I searched the web, you all said that a bean with annotation "LocalBean" is a "no-interface-view".
Is that able to work? or should I create a Local interface and remove the LocalBean annotation?
deeper thoughts... if "remote-view", "local-view" and "no-interface-view" are 3 types of view which can all exist in one bean....? can i have a bean that implements all of them?
#Local
#Remote
#LocalBean
public class Possible implements PosLoca, PosRemote {}
.... i'm really confused...
Yes, it is possible for a bean to expose multiple views (Remote business, Local business, no-interface).
The component can be the same - you just add another ways of accessing it.
Take a look at EJB 3.1 FR specification:
4.4.2.2 Session bean exposing multiple client views (p. 86).
package com.acme;
#Singleton(name="Shared")
#LocalBean
#Remote(com.acme.SharedRemote.class)
public class SharedBean { ... }
One note - I don't think the example you posted will work out-of-the-box. You're using #Remote and #Local without specifying the interface references. I don't think the container will now which interface is what. Either specify the #Remote(clazz) or annotate the interface itself as #Remote.

How to inject one EJB 3.1 into another EJB

I'm developping simple app where one EJB should be injected into another. I'm developping in IDEA Jetbrains IDE. But after i make #EJB annotation in Ejb local statless class my IDE highlight it with error:
EJB '' with component interface 'ApplicationController' not found.
Can anyone tell Why?
Injection of an EJB reference into another EJB can be done using the #EJB annotation. Here is an example taken from Injection of other EJBs Example from the OpenEJB documentation:
The Code
In this example we develop two simple
session stateless beans (DataReader
and DataStore), and show how we can
use the #EJB annotation in one of
these beans to get the reference to
the other session bean
DataStore session bean
Bean
#Stateless
public class DataStoreImpl implements DataStoreLocal, DataStoreRemote{
public String getData() {
return "42";
}
}
Local business interface
#Local
public interface DataStoreLocal {
public String getData();
}
Remote business interface
#Remote
public interface DataStoreRemote {
public String getData();
}
DataReader session bean
Bean
#Stateless
public class DataReaderImpl implements DataReaderLocal, DataReaderRemote {
#EJB private DataStoreRemote dataStoreRemote;
#EJB private DataStoreLocal dataStoreLocal;
public String readDataFromLocalStore() {
return "LOCAL:"+dataStoreLocal.getData();
}
public String readDataFromRemoteStore() {
return "REMOTE:"+dataStoreRemote.getData();
}
}
Note the usage of the #EJB annotation
on the DataStoreRemote and
DataStoreLocal fields. This is the
minimum required for EJB ref
resolution. If you have two beans that
implement the same business
interfaces, you'll want to the
beanName attribute as follows:
#EJB(beanName = "DataStoreImpl")
private DataStoreRemote dataStoreRemote;
#EJB(beanName = "DataStoreImpl")
private DataStoreLocal dataStoreLocal;
Local business interface
#Local
public interface DataReaderLocal {
public String readDataFromLocalStore();
public String readDataFromRemoteStore();
}
(The remote business interface is not
shown for the sake of brevity).
If it doesn't work as expected, maybe show some code.
I believe it's an IntelliJ IDEA bug. This thread solved the problem for me:
adding a EJB Facet (in project structure > modules) helped

Categories