Loading data on bean creation

I have a bean that is responsible for some calculations that depend on data in the database. It’s in the global module and I tried injecting DataManager and doing following:

@PostConstruct
public void init() {
    this.mydata = dataManager.load(MyClass.class).list();
}

But I get the following nested exception: application context is not initialized

Any idea how this should be done instead?

Hi,

When @PostConstruct is called, neither spring context nor application are not fully initialized, and you can not access database yet.

You need to react on one of these events: Application Lifecycle Events - CUBA Platform. Developer’s Manual

If I do something like:

@EventListener(AppContextInitializedEvent.class)
@Order(Events.LOWEST_PLATFORM_PRECEDENCE)
protected void appInitialized() {
    myData = dataManager.load(MyClass.class).list();
}

I get instead an exception in DataService: User session not found: 23d…

Hi,
That’s right, the code need system authentication so that DataManager would know whether to apply any security restrictions to the result list.

First, I would suggest to move the bean either to the core or to the web module, or at least separate bean implementations.
Because core and web use different system authentication methods.

For beans in the core module - you need to wrap dataManager call into the System Authentication block:
https://doc.cuba-platform.com/manual-7.1/system_authentication.html

For web module - I suggest using a com.haulmont.cuba.client.sys.cache.CacheUserSessionProvider bean.

Here are working code samples for CUBA 7.1:

@Component(SuperCache.NAME)
public class CoreSuperCacheBean implements SuperCache {

    @Inject
    protected DataManager dataManager;

    private List<User> cachedUsers;

    @Inject
    protected Authentication authentication;

    @EventListener
    public void onApplicationContextStarted(AppContextStartedEvent event) {
        cachedUsers = authentication.withSystemUser(() -> {
            return dataManager.load(User.class).list();
        });
    }

    @Override
    public List<User> getCachedUsers() {
        return cachedUsers;
    }
}
@Component(SuperCache.NAME)
public class WebSuperCacheBean implements SuperCache {

    @Inject
    protected CacheUserSessionProvider cacheUserSessionProvider;

    private List<User> cachedUsers;

    @Inject
    protected DataManager dataManager;

    @EventListener
    public void onApplicationContextStarted(AppContextStartedEvent event) {
       UserSession userSession = cacheUserSessionProvider.getUserSession();
        if (userSession == null) {
            return;
        }
        try {
            AppContext.setSecurityContext(new SecurityContext(userSession));

            cachedUsers = dataManager.load(User.class).list();
        } finally {
            AppContext.setSecurityContext(null);
        }
    }

    @Override
    public List<User> getCachedUsers() {
        return cachedUsers;
    }
}

Finally, if you want to cache some data on the web layer, I would suggest you to study and use com.haulmont.cuba.client.sys.cache.ClientCacheManager and com.haulmont.cuba.client.sys.cache.CachingStrategy classes. They provide

These are internal classes and they are not documented, however they are used in several places by the CUBA itself and you will save your bugfixing time if adopt them.