Jordi
Jordi

Reputation: 23207

CDI producer reached once

I've created this producer:

@RequestScoped
public class StripeWebHookProducer {

    private static String HEADER_SIGNATURE = "Stripe-Signature";

    @Inject @Context private HttpServletRequest request;

    @Produces
    public Event getStripeEvent() {
        Event result = null;
        //...
        return result;
    }
}

As you can see it's scoped at @RequestScoped, so as far I've been able to figure out it should be created each time a request is reached on server.

I'm injecting it on my servlet:

@WebServlet(...)
public class StripeWebhook extends HttpServlet {
    @Inject private Event paymentEvent;

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            switch (this.paymentEvent.getEventType())
            {
                case customer_subscription_trialwillend:
                    break;
                case customer_subscription_updated:
                    break;
            }
            // TODO Auto-generated method stub
            doGet(request, response);
        }
    }

Nevertheless, StripeWebHookProducer.getStripeEvent is reached only once. Any ideas?

Upvotes: 2

Views: 692

Answers (2)

Siliarus
Siliarus

Reputation: 6753

Seems like you mismatched annotations on class/bean and on producer method. The thing is, producer method has to be placed inside some CDI bean. In your case this bean is StripeWebHookProducer and you have it @RequestScoped annotation. That's perferctly fine, however, it seems accidental so you might want to re-think that and use another one such as @ApplicationScoped or @Dependent

Now the producer method itself. The outcome of producer is not affected by annotations on the CDI bean where the producer resides. Instead, it is defined by annotation on that method. Here is some code with explanation.

@ApplicationScoped
public class MyBeanWithProducer {
  @Produces
  @Dependent
  public ProducedBean produceIt() {
  }
}

The above sample is a CDI bean MyBeanWithProducer with application scope. It containts a producer method capable of creating another CDI bean, ProducedBean, which will have scope @Dependent. Note that the scope of produced bean differs from the scope of MyBeanWithProducer. If you define no scope on the producer method, it is @Dependent by default.

So, what you probably want in your app might look like this:

@ApplicationScoped // ensures there is only one instance of this bean in your app; assuming you have have no other request based logic here
public class StripeWebHookProducer {

    private static String HEADER_SIGNATURE = "Stripe-Signature";

    @Inject @Context private HttpServletRequest request;

    @Produces
    @RequestScoped // this will make sure this bean is created on every request anew
    public Event getStripeEvent() {
        Event result = null;
        //...
        return result;
    }
}

Upvotes: 4

Nikos Paraskevopoulos
Nikos Paraskevopoulos

Reputation: 40296

The producer may be @RequestScoped but the produced bean is @Dependent! To make it request scoped as intended, simply annotate the producer method:

@Produces @RequestScoped
public Event getStripeEvent() {
    ...
}

Upvotes: 1

Related Questions