简体   繁体   中英

CDI producer not recognized with qualifiers

I have an EAR application with 2 modules. A WEB and an EJB module.

There are several services in the EJB module which are injected into classes of the WEB module, which works fine. But some services need configurations based on the user context which is only available in the WEB module. So I tried to add a producer to the WEB module.
The structure looks like this:

app-ear
|
+- app-ejb
|   |
|   +- Service
|   +- ServiceConnector
|
+- app-web
    |
    +- ServiceConnectorProducer

Here is a simplified version of that code:

Service class which gets a connector injected into: (EJB)

public class Service {
    @Inject
    private ServiceConnector connector;
}

Connector class which will handle the connection for a service: (EJB)

public class ServiceConnector {
    private final Config config;

    public ServiceConnector(final Config config) {
        this.config = config;
    }
}

Producer for ServiceConnector : (WEB)

public class ServiceConnectorProducer {
    @Produces
    public ServiceConnector produce(UserContext userCtx) {
        // ... create config and set data from user context
        return new ServiceConnector(config);
    }
}

At this point the producer is not recognized at the injection point and I get an unsatisfied dependency error:

org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type ServiceConnector with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject private Service.connector
  at Service.connector(Service.java:0)

This happen even though the producer was loaded by the container:

WELD-000106: Bean: Producer Method [ServiceConenctor] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces public ServiceConenctorProducer.produce(UserContext)]

When I make the ServiceConnector discoverable by the container by adding a default constructor I however get an ambiguous dependencies error:

Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type ServiceConnector with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject private Service.connector
at Service.connector(Service.java:0)
Possible dependencies: 
- Producer Method [ServiceConnector] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces public ServiceConnector.produce(UserContext)],
- Managed Bean [class ServiceConnector] with qualifiers [@Any @Default]

After that I tried the following things to resolve the ambiguous dependencies.
- https://stackoverflow.com/a/22985035 (Add qualifier)
- https://stackoverflow.com/a/36056972 (Use @Any )
- https://stackoverflow.com/a/29449040/11117616 (Use @Vetoed )

But all these solutions lead back to the unsatisfied dependency error.

WELD-001408: Unsatisfied dependencies for type ServiceConnector with qualifiers @SessionService
  at injection point [BackedAnnotatedField] @Inject @SessionService private Service.connector
  at Service.connector(Service.java:0)
WELD-001475: The following beans match by type, but none have matching qualifiers:
  - Managed Bean [class ServiceConnector] with qualifiers [@Any @Default]

So now I am out of ideas how to resolve the situation. How can I get the ServiceConnector to be produced in the WEB module?

You are most likely observing a Java EE umbrella spec visibility limitation. There are limitations to what certain archives (EAR/lib, EJB jar, WAR) in EAR can see and access. CDI then follows the same pattern with injection.

The implementation of these rules can very slightly differ based on how application servers interpret the specification. Now if you don't feel like reading the spec (who does, uh? ;-)), then you can look at this SO answer that kind of sums up it although not exhaustively.

Namely in your case the WAR file can access contents of EJB but not vice versa. In CDI terms that means that the EJB jar does not "see" the producer method you have there.

As for the ambiguous dependency exception you saw when you made ServiceConnector a bean - I am not 100% sure what that is without a reproducer and some debugging. It could be a bug in how validation is done in EARs or it could be intended because theoretically from WAR archive you can see two beans of type ServiceConnector .

As for how to workaround this - one thing I can think of are CDI extensions which (in Weld's interpretation) span across the whole EAR. Thefore using a CDI extension to register a bean might work for you regardless of what archive does that. If you go that way, look at AfterBeanDiscovery observer and register the bean there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM