On 24.7.2014 17:36, Stian Thorgersen wrote:
>> Why would a provider not be tied to a session? IMO there
should always be a
>> > >session.
>> > >
> >
> >It might be expensive to create the provider and/or the provider may
> >have no concept of a session. For example, Picketlink PartitionManagers
> >are not tied to a KeycloakSession
That's exactly why a ProviderFactory has application scope. Anything that is
expensive to create should be stored in the ProviderFactory and reused in Provider
instances.
For example JpaConnectionProviderFactory creates one EntityManagerFactory (which is
expensive) and reuses it to create a EntityManager for each JpaConnectionProvider.
IMO we need something like "global" providers or "global"
components.
Right now just ProviderFactories are supposed to be global (application
scoped) and providers are supposed to be session scoped, but there may
be usecases for having "global" component, which is itself not
ProviderFactory.
Usually it's needed when the component itself needs access to
KeycloakSessionFactory because it needs to perform some long-running
task, when it manages multiple session/transaction lifecycles. Example
is export/import (or in the future ChronJob for sync many thousand users
from LDAP to local store)
Right now what I am doing for export/import is creating session just for
retrieving ExportProvider or ImportProvider and then particular
ExportProvider or ImportProvider is starting it's own
session/transaction lifecycles whenever it needs them -
https://github.com/keycloak/keycloak/blob/master/export-import/export-imp...
. It's kind of a hack IMO...
Maybe we can have concept of multiple transactions per single
KeycloakSession (for example JPA supports multiple transactions per
single EntityManager but not sure if it doesn't have performance
penalties as some objects are cached per EntityManager etc)
Not sure what is best solution for this, but I wonder if we have Spi for
"global" components, ie. something like this on KeycloakSessionFactory:
<T extends GlobalProvider> T getGlobalProvider(Class<T> clazz);
<T extends GlobalProvider> T getGlobalProvider(Class<T> clazz, String id);
And GlobalProvider itself will have method for injecting
KeycloakSessionFactory:
public interface GlobalProvider {
public void setKeycloakSessionFactory(KeycloakSessionFactory
sessionFactory);
public void init(Config.Scope config);
public void close();
public String getId();
}
Marek