The question in general is: does CDI injection works when a CDI bean is created via a producer field in a JAX-RS service (WAR file) while its consumption is made within EJB bean (EJB file)?
Based on this question Is it possible to @Inject a @RequestScoped bean into a @Stateless EJB? such scenario should work but I can't get this working.
Here are some details. I've a very simple JavaEE application (https://github.com/kocherovms/develorium.com/tree/master/cdi_problem) with following structure:
hello-ear:
|
+- hello-ejb
| |
| +- HelloBean
|
+- hello-war
|
+- HelloService
In this application I'm trying to pass via CDI injection a Guest
object between JAX-RS service (hello-war) and EJB bean (hello-ejb). Here is the JAX-RS service which produces an instance of a Guest
object:
@Path("/hello")
public class HelloService {
@EJB
private Hello hello;
@Produces
@RequestScoped
@GuestMarker
private Guest guest;
@GET
public Response perform() {
guest = new Guest();
guest.setName("white rabbit");
String text = hello.getHelloText();
return Response.ok().type(MediaType.TEXT_PLAIN).entity(text).build();
}
}
Implementation of Hello
from hello-ejb tries to consume a Guest
object via CDI @Inject
:
@Stateless
public class HelloBean implements Hello {
@Inject
@GuestMarker
Guest guest;
@Override
public String getHelloText() {
return String.format("Hello, %s!\n", guest.getName());
}
}
I'm deploying this application into WildFly 10 server. Deployment itself works fine and my service is working. However invocation of a service ( curl http://localhost:8080/hello
) always returns 'Hello, null!' instead of 'Hello, white rabbit!'.
This means that a Guest
object produced on HelloService
side is not available within HelloBean
and a default constructed Guest
instance is used.
I've tried various scopes (e.g. SessionScoped
, ApplicationScoped
), tried to use a producer method, tried making bean to be stateful and even singleton. Nothing works. It seems CDI is always using a Dependant
scope for my case.
Is it possible to pass an instance of a Guest
object from HelloService
to HelloBean
?
I think you might be over complicating your setup. Producer fields are evaluated once, so the fact that you're mutating it is an issue. Your producer should look like
@Produces
@RequestScoped
@GuestMarker
private Guest guest = new Guest();
And then just call the setter in the JAX-RS method, instead of instantiating it. But that won't solve your problem, now that I realize you're using an EAR. The scope of CDI beans is within the module associated. So the EJB is its own context not shared with your JAX-RS resource.