1

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?

Community
  • 1
  • 1
  • There is no need for those two `guest`s are same instance. Change the `@Produces` annotation with `@Inject` then the container *MAY* inject the same instance for the EJB and the JAX-RS resource. – Jin Kwon May 16 '16 at 05:56
  • Hi, Jin. Changing `@Produces` -> `@Inject` is not something I need. What I need is that the same bean under `@Produces` in JAX-RS (HelloService) is available at injection point in EJB (HelloBean). By doing this I want to convey some context information from JAX-RS to EJB. – Michael Kocherov May 16 '16 at 18:34

1 Answers1

0

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.

John Ament
  • 11,595
  • 1
  • 36
  • 45
  • John, seems you are right regarding context sharing. After I've moved HelloBean into the war file (next to HelloService) the issue is gone. Anyway can you point me where I could read about CDI beans visibility related to my issue? Thanks! – Michael Kocherov May 16 '16 at 18:27