I'm trying to implement dependency injection in my Java SE program using weld and I have problems using an application scoped producer. This is a PoC of my problem with minimal code. The MyBean
class:
public class MyBean implements Serializable{
private int value;
public MyBean(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
The injection point:
@Path("api")
public class MyResource implements Serializable {
@Inject
private MyBean bean;
@GET
@Path("bean")
@Produces(MediaType.APPLICATION_JSON)
public Response getBean() {
return Response.ok(bean).build();
}
}
The producer that I want it's produced instance be @ApplicationScoped
is:
public class BeanProducer {
@Produces
@ApplicationScoped
public MyBean beanProducer(){
System.out.println("producing");
return new MyBean(42);
}
}
And it all bound together in a main class:
public class Main {
public void main(@Observes ContainerInitialized event) {
try {
URI baseUri = UriBuilder.fromUri("http://localhost").port(1234).build();
ResourceConfig config = new ResourceConfig(MyResource.class)
.register(JacksonFeature.class);
SimpleServer server = SimpleContainerFactory.create(baseUri, config);
System.in.read();
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
When I try to run this, I get following exception:
Exception in thread "main" org.jboss.weld.exceptions.DeploymentException: WELD-001410: The injection point [BackedAnnotatedField] @Inject @ApplicationScoped private MyResource.bean has non-proxyable dependencies at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:392) at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:293) at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:134) at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:167) at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:530) at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:68) at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:66) at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:60) at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:53) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001435: Normal scoped bean class MyBean is not proxyable because it has no no-args constructor - Producer Method [MyBean] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces @ApplicationScoped public BeanProducer.beanProducer()]. at org.jboss.weld.util.Proxies.getUnproxyableClassException(Proxies.java:214) at org.jboss.weld.util.Proxies.getUnproxyableTypeException(Proxies.java:178) at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:390) ... 12 more
If I define a scope for producer, it won't work.
If I set the injection point scope as @ApplicationScoped
and producer without any scope, it works as I want, means I will have a single instance of the bean in the entire lifecycle of my app.
But setting the scope of the injection point as @ApplicationScoped
is the same as default scope, ie. a new instance for each request.
What is the reason behind all of this?