Apache Jena Initialization

Jena has a simple initialization sequence that is used to setup components available at runtime.

Application code is welcome to also use this mechanism. This must be done with care. Java initialization can lead to visibility of uninitialized data.

The standard initialization sequence is
Core -> RIOT -> ARQ -> TDB -> other (SDB, jena text, jena spatial)

The sequence from core to TDB should be executed before application components. See below for how to control the order.

Initialization occurs when JenaSystem.init() is first called. Jena ensures that this is done when the application first uses any Jena code by using class initializers.

Initialization code

Initialization code is an implementation of JenaSubsystemLifecycle. For use in the default initialization, the class must have a zero-argument constructor

public interface JenaSubsystemLifecycle {
    public void start() ;
    public void stop() ;
    default public int level() { return 9999 ; }
}

The code also supply a level, indicating its place in the order of initialization. The levels used by Jena are:

  • 0 - reserved
  • 10 - Used by jena-core
  • 20 - RIOT
  • 30 - ARQ
  • 40 - TDB
  • 9999 - other

The Initialization Process

The process followed by JenaSystem.init() is to obtain an instance of JenaSubsystemRegistry, ask it to load() initialization code, then call that code in an order based on declared level. The order of invocation of different initialization code within the same level is undefined and may be different from run to run.

Only the first call of JenaSystem.init() causes the process to run. Any subsequent calls are cheap, so calling JenaSystem.init() when in doubt about the initialization state is safe.

Overlapping concurrent calls to JenaSystem.init() are thread-safe. On a return from JenaSystem.init(), Jena has been initialized at some point.

The Standard Subsystem Registry

The JenaSubsystemRegistry normally used is based on java.util.ServiceLoader. It looks for class resources META-INF/services/org.apache.jena.system.JenaSubsystemLifecycle on the classpath during the load step.

See the javadoc for java.util.ServiceLoader for more details.

See also the javadoc for JenaSystem and the source code.

Debugging

There is a flag JenaSystem.DEBUG_INIT to help with development. It is not intended for runtime logging.

Jena components print their initialization beginning and end points on System.err to help track down ordering issues.

Modifying the Standard Process

It is possible, with care, to alter the way that initialization code is discovered.

An application can change the JenaSubsystemRegistry instance. This must be done before any Jena code is called anywhere in the current JVM.

// Example alternative registry.
JenaSubsystemRegistry r = new JenaSubsystemRegistryBasic() {
    @Override
    public void load() {
        if ( JenaSystem.DEBUG_INIT )
            System.err.println("Example custom load") ;
        super.load();
    }
} ;

// Set the sub-system registry
JenaSystem.setSubsystemRegistry(r);

// Enable output if required
// JenaSystem.DEBUG_INIT = true ;

// Initialize Jena
JenaSystem.init() ;

Jena initialization in multi-classloader environments

In some applications with multiple classloaders, or different classloader strategies, Jena initialization may not work as expected. If the Jena initialization debug information shows that components were not loaded correctly, trying to switch the context class loader may fix the initialization process.

ClassLoader contextClassLoader = null;
try {
    contextClassLoader = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
    JenaSystem.DEBUG_INIT = true;
    // ...
} finally {
    Thread.currentThread().setContextClassLoader(contextClassLoader);
}