15

Here is the situation.

I've got the following interfaces:

public interface Parent { }
public interface ChildOne extends Parent { }
public interface ChildTwo extends Parent { }

and 2 EJBs:

@Stateless
public class FirstBean implements ChildOne { }

@Stateless
public class SecondBean implements ChildTwo { }

And also this CDI Bean:

@Named
@SessionScoped
public class TestController implements Serializable {

    @Inject
    private FirstBean firstBean;

    @Inject
    private SecondBean secondBean;
}

While trying to deploy this on Glassfish 3.1 I get the following exception:

Exception while loading the app : WELD-001408 Unsatisfied dependencies for type [FirstBean]
with qualifiers [@Default] at injection point [[field] @Inject private com.test.controllers.TestController.firstBean]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [FirstBean] 
with qualifiers [@Default] at injection point [[field] @Inject private com.test.controllers.TestController.firstBean]
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:305)

When both EJBs implement the Parent interface, the exception is the same.
Also, I tried adding qualifiers, but that didn't change anything.

jFrenetic
  • 5,384
  • 5
  • 42
  • 67

3 Answers3

22

I just played around with your construct, read a bit of the weld docu and found out the following.

You are using EJBs that implement an interface, so the no-interface view is not possible anymore (obviously), but you are trying to directly access the implementation. As soon as you declare it as an EJB you have to keep in mind the conventions. So, if you define an interface you have to use it to get access to the EJB. Changing it to the following, should work out:

@Inject
private ChildOne firstBean;

Accessing the implementation even though an interface is defined is just possible for plain CDI Managed Beans (classes without the @Stateless/@Stateful annotations). So get rid of your annotation and it will work out.

Just for your information, if you are using Glassfish. If you stick to your EJBs and try to access the parent interfaces method you will run into this bug / exception.

Community
  • 1
  • 1
  • Thanks a ton! Really good explanation! And I've already bumped into that exception `Unable to convert ejbRef for ejb...`, I just didn't know it's a known issue. – jFrenetic Jan 28 '12 at 10:22
  • I checked it once again. I tried to inject those EJBs by interface reference as you suggested. And I'm still getting this `Unsatisfied dependencies...` exception during deployment. I even annotated the interfaces with @Local. Still it doesn't work. – jFrenetic Jan 28 '12 at 12:21
  • I tried it out yesterday and it worked for me, furthermore it makes quite a bit of sense. Anyway, I will try it out again when I am back home. – Roland Tiefenbrunner Jan 28 '12 at 12:43
  • Thanks again for help. I even uploaded my test application (with source code included) to make things easier. You can get it [here](http://www.mediafire.com/?511zmabosw3wcki) – jFrenetic Jan 28 '12 at 13:05
  • 1
    Sorry, your example surely works. I just totally forgot to add `beans.xml` to my ejb-jar (however I had one for CDI @Named beans). – jFrenetic Jan 28 '12 at 16:12
  • Oh, and I think I just found another more elegant solution. Marking my EJBs with @LocalBean annotation allows me to inject them by implementation class, and the exception that you mentioned when calling abstract class's method doesn't happen. – jFrenetic Jan 28 '12 at 19:13
  • 1
    More elegant depends on the use case i guess :) Just be aware of the drawback. Be sure not to expose implementations of frequently changing classes. Furthermore, you will lose the ability to exchange implemenation on runtime, which is possible using CDI (producer methods, alternatives). However, it is of course not always necessary to program against an interface, especially within Java EE, as explained here: http://www.oracle.com/technetwork/articles/java/intondemand-1444614.html – Roland Tiefenbrunner Jan 30 '12 at 15:32
8

Better late than never:

Annotating the SLSB aditionally with @LocalBean works for me with JBoss AS 7.1.1. I don't like the idea of creating the interface for no added value.

Using your example:

@Stateless
@LocalBean
public class FirstBean implements ChildOne { }

@Stateless
@LocalBean
public class SecondBean implements ChildTwo { }
atamanroman
  • 11,607
  • 7
  • 57
  • 81
  • @atamanroman, do you know if that method is portable ? Because the definition for `@LocalBean` is "Designates that a **session** bean exposes a no-interface view" and as it's not a "session" bean here, will it work everywhere and is it the right thing to do ? – Anthony O. Nov 22 '12 at 15:59
  • 1
    @AnthonyO. stateless session beans and stateful session beans are both session beans. So yes, this is exactly as the standard requires. – atamanroman Nov 22 '12 at 16:21
0

Have you tried using @EJB annotation rather then the CDI @inject annotation?

E.g.

@Named
@SessionScoped
public class TestController implements Serializable {

    @EJB
    private FirstBean firstBean;

    @EJB
    private SecondBean secondBean;
}
juan.villa
  • 231
  • 1
  • 2
  • 5