Вопрос

I have two ManagedBeans.

Concerning my problem, they do the following:

First:

@ManagedBean
public class Provider {

    private Event<ProvideEvent> event;

    private static boolean handling = false;
    public provide(@Observes ConsumeEvent consume){
      if(!handling){
        //provide some stuff
        event.fire(new ProvideEvent(ProvidedStuff stuff);
      }
    }
}   

Second:

@ManagedBean
@SessionScoped
public class Consumer {

    private Event<ConsumeEvent> event;

    @PostConstruct
    public void initialize(){
      event.fire(new ConsumeEvent());  
    }

    private static boolean handling = false;
    public consume(@Observes ProvideEvent providedStuff){
      if(!handling){
        //use the provided stuff
      }
    }
}     

This happens, when the website is called: 1. Consumer is instantiated. 2. Consumer fires the event. 3. Provider is instantiated. 4. provide() is called. 5. A NEW CONSUMER IS INSTANTIATED 6. consume() is called.

As you can see, I had to use a boolean "handling" to keep the application from looping infinitly.

Why is the container not using the instantiated SessionScoped ManagedBean? I thought SessionScoped ManagedBeans are like Singleton for the Session? I guess I could work around this by: A: Using static variables for the changed properties. B: Implementing the Observer-Pattern manually.

But there has to be an easier way here!?

Это было полезно?

Решение

I believe the problem could be that you fire the event in the @PostConstruct method of your Customer.

From the javadocs:

This method MUST be invoked before the class is put into service.

As far as I understand, that results in a race condition. The Provider is probably firing the second event earlier than your Customer instance finishes executing initialize() and the container puts it into service. Hence, it won't receive the event. I'm too inexperienced with Java EE to give good advice how to prevent that race condition though. I would probably work around it with an ugly SynchronousQueue as a meeting point.

Additional info: the default with @Observes is to create a new instance of the event receiver if none exists (is in service). That's why another customer is created. Use @Observes(notifyObserver = Reception.IF_EXISTS) to only notify existing instances that are in service.

I thought SessionScoped ManagedBeans are like Singleton for the Session?

No, it just defines the lifetime of the object(s). It doesn't really enforce session-singleton behavior. The container would probably prefer the existing instance though, if it was in service at the time the second event is fired.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top