2

I have two managed beans which both have an @ApplicationScope annotation:

Storage.java:

@ManagedBean(eager = true)
@ApplicationScoped
public class Storage {

    private static final Logger LOGGER = LoggerFactory.getLogger(Storage.class);

    private List<Sheet> sheets = new ArrayList<Sheet>();

    public List<Sheet> getSheets() {
        return sheets;
    }

    public Sheet load(String id) {
        // ...
    }

    public void storeSheet(Sheet sheet) {
        sheets.add(sheet);
        LOGGER.trace(""+this.hashCode()+" Stored sheet: "+sheet);
    }

    public void delete(Sheet s) {
        sheets.remove(s);
        LOGGER.trace(""+this.hashCode()+" Removed sheet: "+s);
    }

}

StorageInitializer.java:

@ManagedBean(eager = true)
@ApplicationScoped
public class StorageInitializer {

    @ManagedProperty(value = "#{storage}")
    private Storage storage;

    @PostConstruct
    public void init() {
        int nofSheets = 10;
        int min = 20;
        int max = 200;
        for (int i=0; i<nofSheets; i++) {
            storage.storeSheet(new Sheet(
                    "Sheet "+i,
                    ThreadLocalRandom.current().nextInt(min, max),
                    ThreadLocalRandom.current().nextInt(min, max)));
        }
    }

    public void setStorage(Storage storage) {
        this.storage = storage;
    }

}

When the application starts, StorageInitializer should write 10 instances into the storage. Other beans with @RequestScoped do access the store and make the sheets visible. They all have a

    @ManagedProperty(value = "#{storage}")
    private Storage storage;

to access the Storage bean.

By logging the hash I can see that I sometimes get two instances of the Storage bean. The first one gets initialized by StorageInitializer. The second one gets used by the @RequestScoped beans and is empty.

To mee this looks like a race condition or timinig problem. If I set a break point in StorageInitializer.ini() everything works ok.

Any ideas?

BetaRide
  • 16,207
  • 29
  • 99
  • 177
  • What package did you import `@ApplicationScoped` annotation from? – BalusC Mar 23 '16 at 11:11
  • javax.faces.bean.ApplicationScoped – BetaRide Mar 23 '16 at 11:12
  • In both instances? Provided all those classes are in WAR (and thus not EAR) then your runtime classpath is most likely polluted with multiple different versioned JSF libraries. Check and cleanup it. – BalusC Mar 23 '16 at 11:15
  • Have you put an `sysout` in both `StorageInitializer.init()` and in managed beans to see what comes first? If is a race condition then we could use some `java.util.concurrent` structure – Johnny Willer Mar 23 '16 at 11:19
  • @Johnny: JSF API forbids multiple application scoped beans in first place, so any assumption based on this being correct behavior is incorrect. – BalusC Mar 23 '16 at 11:20
  • @BalusC the way I understood the question, OP seems to say 2 two different instances but not in same time. e.g application run 1 gets a complete initialized Store. run application 2 gets an empty Storage – Johnny Willer Mar 23 '16 at 11:21
  • @BalusC So I should have only one bean with application scope? Do you have any references for this? I'm wondering that I do not get an Exception because this could be easily detected. – BetaRide Mar 23 '16 at 11:45

1 Answers1

0

I had the same problem with two @ApplicationScoped beans with "eager = true". The duplicated bean was in a @ManagedProperty in the other @ApplicationScoped bean. I solved the problem by changing the eager value to false on the bean that owned the @ManagedProperty. In my case the eager value wasn't strictly necessary.