As input, a WireContext takes a {@link WireDefinition}. The WireDefinition contains named {@link Descriptor}s that know how to create objects and wire them together. Each object has a name. The WireContext will maintain a cache (map) of the created objects. So that upon subsequent requests, the same object can be given from the cache.
A WireContext is used often in combination with {@link Environment} to decouple the processDefinition virtual machine from its environment. In the {@link DefaultEnvironmentFactory}, both the application context and the block context are WireContexts. The PVM will use the persistence service, asynchronous message service, timer service and other services through specified abstractions in the environment.
Another usage of the WireContext is construction and configuration of user code objects in a persistable way. {@link Activity}s and {@link org.jbpm.pvm.ExternalActivity}and other user code can be instantiated with a WireContext. That way, they can be persisted in a fixed schema.
Each {@link ProcessElementImpl} has configuration properties.Consider this extra metadata that can be associated to elements in a processDefinition definition. In that respect, it's somewhat similar to what annotations are in Java. Because of the wire persistence, all these configuration properties fit into the same process model and in its database schema.
Mostly often, {@link Descriptor}s and WireContext's are not used directly. Instead, the wire XML is used in a configuration file. The {@link WireParser wire XML parser} contains the documentation onthe XML grammer. The {@link WireParser} will produce a {@link WireDefinition}with a bunch of {@link Descriptor}s in it.
Objects are build in 2 phases: construction and initialization. The motivation for splitting these phases is to resolve many of the circular dependencies. Imagine 2 objects that have a bidirectional reference. By splitting the construction from the initialization phase, the objects can both be constructed first, and then during initialization, they will be injected into each other.
Construction of the object is all that needs to be done until a reference to the object is available.
In the case of dynamically created objects ( {@link ObjectDescriptor}), the simplest case this is accomplished with a constructor. But also static or non-static factory methods can be used to obtain a reference to an object.
In case of immutable objects, the descriptor can just provide a reference to a singleton object.
Initialization is optional and it is comprised of everything that needs to be done with an object after a reference to the object is available. {@link AbstractDescriptor} contains an empty default initialization method.
For objects {@link ObjectDescriptor}s, this means that a a sequence of {@link Operation}s can be applied to the object. Following operations implementations are already available and can be applied to an object during initialization:
When an environment is injected into a WireContext, lookup of all referenced object names will be done first in this WireContext, but if the object name is not defined there, the environment will be searched in the environment's default search order.
Several objects will fire events to which can be subscribed:
The WireContext itself fires the {@link #EVENT_OPEN} and {@link #EVENT_OPEN}events.
The {@link Descriptor}s will fire the events {@link Descriptor#EVENT_CONSTRUCTING}, {@link Descriptor#EVENT_INITIALIZING}, {@link Descriptor#EVENT_CONSTRUCTED}, {@link Descriptor#EVENT_SET} and {@link Descriptor#EVENT_REMOVE}.
And last but not least, the objects created by the WireContext can be {@link Observable} themselves.
By default, all objects in a WireContext are lazily constructued and initialized. Eager initialization is specified on a named object and it means that the object is constructed and initialized during construction of the WireContext. You an only specify eager initialization when the object has a name.
The initialization can be specified with the {@link AbstractDescriptor#setInit(char)} method.
The possible value forinit
parameter is one of :
|
|
|
|
|
|
|
|
|
|
|
|