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.
See notes on repacking Jena code for how to deal with ServiceLoader files in repacked jars.
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:
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 JenaSubsystemRegistry
normally used is based on java.util.ServiceLoader
.
It looks for class resources
META-INF/services/org.apache.jena.sys.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.
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.
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() ;
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); }