Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency injection through constructor does not work for EJB bean

My app is being deployed on to IBM WebSphere. I have a simple service and I'd like to know how dependency injection works in this case.

// stateless EJB
@Stateless
public class UserService {

    private UserDAO userDAO;

    // btw, UserDAO is stateless EJB as well
    @Inject
    public UserService(UserDAO userDAO) {
        this.userDAO = userDAO;    
    }

    // biz methods ...
}

It fails with the following error:

[ERROR ] CWWKZ0002E: An exception occurred while starting the application my-app. The exception message was: com.ibm.ws.container.service.state.StateChangeException: com.ibm.ws.cdi.CDIException: com.ibm.wsspi.injectionengine.InjectionException: com.ibm.ejs.container.EJBConfigurationException: EJB class com.demo.app.UserService must have a public constructor that takes no parameters

I remember there was something in EJB spec that says: the class must have a public constructor that takes no parameters and it makes sense for me that the bean instance is first instantiated by the container and afterward dependency injection is done.

On the other hand, I've found this in WELD docs:

First, the container calls the bean constructor (the default constructor or the one annotated @Inject), to obtain an instance of the bean.

And I am confused a little bit, why my EJB cannot be instantiated.

How is the EJB instance being created and dependencies injected when we have constructor injection point?

Any ideas? :)

like image 837
ikos23 Avatar asked Dec 23 '22 02:12

ikos23


1 Answers

So what happens is that you do not meet the requirements for initializing EJB beans.

CDI spec has some limitations on constructors - either no-args or one with @Inject. But there is also this chapter, which specifies that in EE, the set of rules is extended by what EJB session beans require.

And now we are getting into EJB spec which requires a no-arg constructor on a bean. This should be in chapter Enterprise Bean Class where it states

The class must define a public constructor that takes no arguments.

Now, finally moving on to whether this should work - e.g. can you have an EJB bean using CDI constructor injection? Well, let's have a look at CDI TCK, a set of tests that all implementation and containers have to pass in order to be able to claim they implement CDI. There, we can see this bean and this test using it - so yea, this can work, but you need to have both constructors.

like image 173
Siliarus Avatar answered May 14 '23 12:05

Siliarus