0

I'm wondering what is the best approach to notify EJB/Seam sessions beans about data changes in an application scoped bean.

In my use case I have a central (application scoped) seam2 bean that communicates with different services to keep the application data up to date. As soon as anything changes I need to notify all my current user sessions about the changed data, that they can pick it up as soon as they can. What is the best way to achieve this?

I've tried the @RaiseEvent, @Observer approach of Seam, but it seems not possible to notify beans in SessionScope from ApplicationScope.

I'm using JEE5, Seam2, EJB3.0

Thanks

Richard
  • 582
  • 5
  • 19

1 Answers1

0

If found a solution, which needs a little trick to work.

First of all I have created two new interfaces in my project:

public interface IDataProvider {

    public void register(IDataObserver observer);

    public void unregister(IDataObserver observer);
}

public interface IDataObserver {
    public void update();
}

As a second step I implemented the two interfaces in my beans.

@Name(ApplicationBean.BEAN_NAME)
@Scope(ScopeType.APPLICATION)
public class ApplicationBean implements IDataProvider {
    private Set<IDataObserver> observerList = new HashSet<IDataObserver>();

    @Override
    public void register(IDataObserver observer) {
        this.observerList.add(observer);

    }

    @Override
    public void unregister(IDataObserver observer) {
        this.observerList.remove(observer);
    }

    public void notifyAllObserver() {
        for(IDataObserver observer : observerList) {
            observer.update();
        }
    }
}

@Name(SessionBean.BEAN_NAME)
@Scope(ScopeType.SESSION)
public class SessionBean implements IDataObserver {

    @Create
    public void init() { 
        // inject dependencies
        injectBeans();

        // register at the dataserviceprovider to be notified about data changes
        dataProviderService.register(this);
    }

    private void injectBeans() {
        dataProviderService = (DataProviderService) Component.getInstance(
                DataProviderService.BEAN_NAME, ScopeType.APPLICATION);
    }

    @Destroy
    public void shutDown() {  
        dataProviderService.unregister(this);
    }

    @Override
    public void update() {
        // grab data from 
    }
}

Please be aware that this approach only works if you inject your seam components via Component.getInstance() and not via @In. In the later case you will always get null for them as soon as update() gets called!

Richard
  • 582
  • 5
  • 19
  • Using the "classical" observer-pattern isn't a good idea while dealing with Seam-Components. Keeping references to Seam-Components is not recommended - all Seam-mechanisms will not work (e.g. http://seamframework.org/Documentation/CanIHoldAReferenceToASeamComponentSuchAsInAList). Anyway - in your update-method you could get an instance of that component in Seam-context. Just use `Component.getInstance(BEAN_NAME)` and do everything on this "new" object. – MrD Aug 07 '13 at 11:55
  • One additional note: the method you are calling on the component in Seam-context must not be private. It seems that the Seam-proxy does not wrap private methods. – MrD Aug 07 '13 at 12:28
  • Thanks for your advice, I see my error and changed my injection code accordingly. I would also love to stick with the standard seam event mechanism to implement my observer pattern, but unfortunately I did not get it running between application scoped and session scoped beans. Between application scoped beans it works very well. – Richard Sep 17 '13 at 06:11