CDI Ambiguous dependencies - java

I have a #SessionScoped #Named bean with a #Producer method for a user object:
#Named #SessionScoped
public class UserBean implements Serializable
{
//...
#Named #Produces #LoggedIn #SessionScoped
public MyUser getCurrentUser() {return user;}
}
This works fine in my setup (JBoss-7.1.1-Final) and it's no problem to access the user fields from JSF pages with #{currentUser.name}. The qualifier is org.jboss.seam.security.annotations.LoggedIn. Now I want to #Inject this user in a field in another #Named Bean:
#Named
public class FavBean implements Serializable
{
private #Inject #LoggedIn MyUser currentUser;
}
This gives me the error:
org.jboss.weld.exceptions.DeploymentException:
WELD-001409 Ambiguous dependencies for type [MyUser] with qualifiers [#Default] at
injection point [[field] #Inject #LoggedIn test.FavBean.currentUser].
Possible dependencies [[Managed Bean [class test.ejb.MyUser] with qualifiers
[#Any #Default],
Producer Method [MyUser] with qualifiers [#Any #Default] declared as [[method]
#Named #Produces #LoggedIn #SessionScoped public test.UserBean.getCurrentUser()]]]
I don't understand the first dependency Managed Bean [class test.ejb.MyUser] This class is a simple #Entity and deployed in an ebb.jar in a EAR. As a workaround I'm currently injecting the UserBean get the user from there.

This is because CDI searches for beans by type and your entity and the producer method return the same type. That's why it is ambiguous.
You need to define a new qualifier and annotate it with your producer method.
#Qualifier
#Retention(RUNTIME)
#Target({METHOD, FIELD, PARAMETER, TYPE})
public #interface CurrentUser {
}
Add this annotation to your producer method:
#Named #Produces #CurrentUser #LoggedIn #SessionScoped
public MyUser getCurrentUser() {return user;}

I had very similar problem, and I got some offline help. My problem was that where my service was, it was included in a deployed ear AND in my web project as well. It was an accidental duplication, drop one out, and it will work if it is your case as well.
here on the following picture I had the esb_khr inside the esb_khr_web, I removed. In eclipse: go to properties and deployment assembly.

I'm not an expert but I had a similar problem, and I fixed it in simpler way, by annotating the bean itself with #Alternative, so that the Producer is favored. Could be I'm missing some side effects but this worked as far as I could see / needed.

Please double check that you do not have multiple instances of beans.xml in your context. In my case I had beans.xml in WEB-INF and in META-INF. After removing beans.xml from META-INF, the similar issue got resolved.

Related

CDI Producermethod ignored

I am totally at a loss! I have this Class:
package com.company.resources
import com.company.transport.Repository; //an interface for an EJB
import com.company.transport.Expression; //a simple DTO, returned by the Interface
public class ResourceProducer
{
//#EJB(lookup="foo") Repository repo;
#Produces #Named("archive")
public String getArchiveString() {
return "archive";
}
#Produces #Named("repository")
public Repository getRemoteRepository(){
//return repo;
return new Repository(){
#Override
public Expression getExpression(String s, Long aLong) {
return null;
}
};
}
}
And, simply put the String one works, the other one is ignored by the container (Wildfly 9 / Weld).
At the begining I wanted to inject an EJB and getRemoteRepository was not annotated as #Named, as i only know supply one Producer for the interface Repository. Getting the errors, i changed them to be the same, to limit the scope for the error, even in the Injection Points:
package com.company.resources
public Class ExpressionProxy {
#Inject #Named("archive") String target;
#Inject #Named("repository") Repositroy repo;
}
I get:
org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type Repository with qualifiers #Default
at injection point [BackedAnnotatedField] #Inject com.company.resources.ExpressionProxy
I do not get this Exception for The String!
Also, if i annotate ResourceProducer with #ApplicationScoped - making it a Bean - I expect getting ambigous bindings - as my Producer now is found via the #Produces Annotation itself and is present in a Managed Bean.
I also only get ambigous binding Exceptions for the String, never for Repository
I moved both classes to one .war and to the same package - it simply wont work with Repository.
I did CDI injection via Interfaces before - what is the Problem here?
EDIT: to give full disclosure:
I deploy this in an ear, as a library:
app.ear/
-jaxrs.war # contains rest interface, irrelevant for this bug
-lib/
-beans.jar #contains the Producer and ExpressionProxy
-RepositoryInterface.jar # containts Repository and Expression
i tried every permutation of the 3 archives involved.
the mentioned
beans and interfaces as library in the .war
beans as additional deployment
beans as additional deployment AND in ear/lib
The beans in /lib obviously get scanned by weld, as the String does not make any problems.
Cited from the Weld documentation 2.2.3
A producer method must be a non-abstract method of a managed bean class or session bean class. A producer method may be either static or non-static. If the bean is a session bean, the producer method must be either a business method of the EJB or a static method of the bean class.
So you could annotate your ResourceProducer with #ApplicationScoped.
Note: Using any modern IDE should tell you, that you are missing the required dependencies on compile. This saves you the time to deploy your application.

How does my container injects a bean which is not marked as #stateful/#stateless, etc?

I am having some problems understanding Java CDI.
I have a stateful bean which receives per injection a some objects:
#Stateful
public class MyBean {
#Inject
private MyDAO myDAO;
}
and this is the DAO:
public class MyDAO{
}
I thought it would not work, because I have not defined the bean as #Stateless, #Stateful, etc.
But it works.
The question is: what scope will this bean have? Will it be a stateful bean?
In this context MyDAO has a Dependent pseudo-scope which means that it will follow the lifecycle of the bean into which it is injected (in your case EJB stateful MyBean bean). Everything explained here.

Using a CDI producer causes ambiguous dependencies exception

I have a requirement to Inject the same instance of an ApplicationScoped bean into several places of my application and have created the following factory class which uses the #PostConstruct annotation to initialize the bean and the #Produces annotation to return the same instance of the bean.
#ApplicationScoped
public class CommandBusFactory implements Serializable {
private static final long serialVersionUID = 1L;
private CommandBus commandBus;
#PostConstruct
public void init() {
commandBus = new BasicCommandBus();
// Do some stuff to configure the command bus
}
#Produces
public CommandBus produceCommandBus() {
return commandBus;
}
}
The problem I've got is when I deploy the application GlassFish returns the following error message:
Exception while loading the app : CDI deployment failure:WELD-001409 Ambiguous dependencies for type [CommandBus] with qualifiers [#Default] at injection point [[BackedAnnotatedField] #Inject private myapp.web.ToDoItemCommandController.commandBus]. Possible dependencies [[Producer Method [CommandBus] with qualifiers [#Any #Default] declared as [[BackedAnnotatedMethod] #Produces public myapp.core.cdi.CommandBusFactory.produceCommandBus()], Managed Bean [class myapp.core.commandhandling.BasicCommandBus] with qualifiers [#Any #Default]]]
I can overcome this exception by adding the #Alternative annotation to the BasicCommandBus class, however this doesn't seem to be the best way of solving the problem.
I don't want to add a qualifier everywhere that I inject CommandBus into my application as using a different implementation of CommandBus would require changing the code in multiple places. The intention is that a later version of the factory will read a configuration file and depending upon a value in the configuration file it may create a different type of CommandBus.
I have read the answer to this question (https://stackoverflow.com/a/18782027/1274662) and understand why the Ambiguous dependencies exception is being thrown but what I don't know is the best way to deal with the fact that there are two possible beans that could be injected given that I want to decide which implementation is used and how it is initialised in a central location.
The questions I've got are:
Is using the #Alternative annotation on the BasicCommandBus class the right approach?
Is there a better approach that I should be using to Inject the same instance of an ApplicationScoped bean (i.e. CommandBus) into several places of my application whilst controlling which implementation created (i.e. BasicCommandBus or EnhancedCommandBus) and how it is initialised in a central location?
If you want your bean to be injectable only by the producer you can annotate BasicCommandBus and EnhancedCommandBus with #Vetoed this way you'll not have the ambiguity between the bean it self and the producer method and at every injection point it's the producer that will inject the instance.

Unsatisfied dependencies for type [...] with qualifiers [#Default] at injection point (using #Stateful EJB with CDI)

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:
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?
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.
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.
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.
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"/>
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.
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.

Testing Stateful Session Beans with Arquillian (arq-jbossas-remote)

I have several #Stateful SessionBeans annotated like this:
#Stateful
#Remote(AdminFacade.class)
public class TAdminFacadeBean implements TgAdminFacade,Serializable
{
...
}
Now I want to test them with Arquillian (1.0.0.Alpha5), but get lot's of different errors, messages vary either if the annotations are #Stateful or #Stateless, if a #Named is added or if there is no #Remote (and implements Interface).
Steps to reproduce:
Create new maven project with
archetype org.jboss.weld.archetypes:jboss-javaee6-webapp:1.0.1.CR2
You might need to set jboss.home (see
readme.txt)
Modify pom.xml and set profiles.profile[id=default].build.plugins.plugin[artifactId=maven-surefire-plugin].configuration.skip
to false
Start JBoss-6.0.0.Final
Execute test (should pass): mvn test -Parq-jbossas-remote
The bean tested here ist MemberRegistration:
#Model
public class MemberRegistration
{
...
}
If you now change #Model to #Stateful, JBoss loops with stacktraces, with #Named #Stateful this error:
java.lang.IllegalArgumentException: ArquillianServletRunner not found.
Could not determine ContextRoot from ProtocolMetadata, please contact
DeployableContainer developer.
#Named #Stateless:
javax.transaction.NotSupportedException: BaseTransaction.checkTransactionState
- ARJUNA-16051 thread is already associated with a transaction!
How can I test my #Stateful Beans with Arquillian?
Over and over again working in this issue I figured out the solution. Even I hate answering my own question I hope this can help somebody in the future.
The annotation for the #Stateful session bean (at the top of the question) are correct and stay the same. In the Arquillian test case the bean was originally injected with
#Inject MemberRegistration memberRegistration;
This works with #Model beans but not with #Stateful session beans and a #Remote interface. It seems this kind of beans must be injected with
#EJB private AdminFacade adminBean;
See What is the difference between #Inject and #EJB

Categories

Resources