19
votes

I have the following code to manage two kinds of repositories. Both repository classes inherit an interface to allow reinitialization of their resources.

public interface CachingRepository
{
    public void invalidateCache();
}

Global, application-scoped repo:

@Named("globalRepo")
@ApplicationScoped
public class GlobalRepository implements CachingRepository
{
    private List<Category> categories;

    ...

    @Override
    public void invalidateCache()
    {
        categories = null;
    }

    ...
}

Per user, session-scoped repo:

@Named("userRepo")
@SessionScoped
//@Stateful         // <- NOTE HERE
public class UserRepository implements CachingRepository, Serializable
{
    private List<MyFile> files;

    @Override
    public void invalidateCache()
    {
        files = null;
    }

    ...
}

When injecting this (without @Stateful) into the context

@Named
@ViewScoped
public class MyHandler implements Serializable
{
    @Inject
    private UserRepository userRepo;

    ...
}

it works. However, when adding @Stateful to the UserRepository class, deployment fails with an exception saying:

Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [UserRepository] with qualifiers [@Default] at injection point [[field] @Inject private de.company.project.pack.MyHandler.userRepo]
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:275)
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:244)
    at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:107)
    at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:127)
    at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:346)
    at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:331)
    at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:366)
    at org.jboss.as.weld.WeldContainer.start(WeldContainer.java:83)
    at org.jboss.as.weld.services.WeldService.start(WeldService.java:76)
    ... 5 more

Adding the name of the CDI bean like

@Inject @Named("userRepo")
private UserRepository userRepo;

results in the same exception. The only thing that works in conjunction with @Stateful is to use the interface in the var declaration:

@Inject @Named("userRepo")
private CachingRepository userRepo;

I might need sub class functionality here however, so using CachingRepository isn't really desired (at the moment).

Q's:

  1. Why isn't this working as expected? The UserRepository var should already identify which class to instantiate, shouldn't it? What's the logic to this?
  2. Why does the @Stateful EJB annotation have such severe effects here? Why does it essentially force me into using the CachingRepository interface in the var declaration?

Note, I' using Seam 3 Faces making the @ViewScoped become a CDI view-scoped bean, so the problem at hand is likely still CDI-only.

5
Oh, and BTW this seems to have been answered to some degree before here stackoverflow.com/questions/9038815/…, but why "if you use an EJB you can't use the implementation anymore"? What's the logic behind this? Why isn't it possible anymore? This convention seems to exist, but why does it at all?Kawu
As I wrote, I don't see any sense it this and I am glad that it's not possible anymore so I can't help with that-)Petr Mensik
Are you aware that you need @Named if and only if you need JSF-access for a CDI managed bean? All it does is providing a qualified EL-name, it does not make a pojo to a CDI managed bean (that is 'done' by beans.xml) ...jan groth
Yes, I do. :-) The repos are displayed as dataTables to select files from and the view-scoped beans basically function as handlers for file uploads/removals (AJAX requests). As soon as one file gets added or removed, the list of respective repo files must be invalidated to be redisplayed. At least that's the current idea.Kawu

5 Answers

11
votes

I had the same problem with this misleading exception...

By adding @Stateful to UserRepository you expose EJB methods of the CachingRepository interface without having a no-interface view declared. Add @LocalBean to UserRepository to activate the no-interface view. See EJB 3.1 Specification, Section 4.9.8 "Session Bean's No-Interface View"

The bean class must designate that it exposes a no-interface view via its bean class definition or in the deployment descriptor. The following rules apply:

  • ...
  • If the bean exposes at least one other client view, the bean designates that it exposes a no-interface view by means of the @LocalBean annotation on the bean class or in the deployment descriptor.
  • ...

I also refer to this stackoverflow answer for more information about no-interface views.

2
votes

I had the same error.

Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type UserTransaction with qualifiers @Default at injection point [BackedAnnotatedField] @Inject...

I solved this problem like this: I used UserTransaction this way when I received an error.

@Inject
UserTransaction trans;

Instead of @Inject, I used @Resource annotation.

0
votes

I had the same problem.

And this is what I did to resolve it:

I had to produce the EJB I am trying to inject as below with a wildfly container:

@ApplicationScoped
    public class Resources {
     private static final String DISCOUNT_SERVICE_ENDPOINT_PROPERTY =
        "services.discount.endpoint";
     private MyServiceImpl myService;
    }

@Produces
 public MyServiceImpl produceMyServiceImpl() {
     if (myService == null) {
         String endpoint = System.getProperty(DISCOUNT_SERVICE_ENDPOINT_PROPERTY);
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(MyServiceImpl.class);
        factory.setServiceName(MyService.SERVICE);
        factory.setAddress(endpoint);
        myService = (MyServiceImpl) factory.create();
     }
     return myService;

}

The below is a config which goes under your standalone-full.xml file.

<property name="services.discount.endpoint" value="http://localhost:8080/my_service/MyService/MyServiceImpl"/>
0
votes

I had the same problem. I hope this can help someone.

To solve the problem:

  • Right click on projcet
  • Click on Properties
  • find Project facets
  • On Project facets, active the option CDI
  • Apply and save.

Now all is fine.

0
votes

Maybe you should add non-parameterized Constructor on the bean class. I read on Jboss Documentation that says: concrete Java class that has a constructor with no parameters (or a constructor designated with the annotation @Inject) is a bean.