Search code examples
jakarta-eejbossejbjax-rscdi

CDI Injection in EJB from WAR doesn't retain original object


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?


Solution

  • 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.