org.jbpm.wire
Class WireContext

java.lang.Object
  extended by org.jbpm.util.DefaultObservable
      extended by org.jbpm.wire.WireContext
All Implemented Interfaces:
java.io.Serializable, Context, Closable, Observable

public class WireContext
extends DefaultObservable
implements Context, Closable, java.io.Serializable

object factory that creates, initializes, wires and caches objects based on descriptors (aka IoC container).

General principle

As input, a WireContext takes a WireDefinition. The WireDefinition contains named Descriptors 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.

Purpose

A WireContext is used often in combination with Environment to decouple the processDefinition virtual machine from its environment. In the 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. Activitys and ExternalActivity and other user code can be instantiated with a WireContext. That way, they can be persisted in a fixed schema.

Each 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.

Xml

Mostly often, Descriptors and WireContext's are not used directly. Instead, the wire XML is used in a configuration file. The wire XML parser contains the documentation on the XML grammer. The WireParser will produce a WireDefinition with a bunch of Descriptors in it.

Object lifecycle

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

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 (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

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. AbstractDescriptor contains an empty default initialization method.

For objects ObjectDescriptors, this means that a a sequence of Operations can be applied to the object. Following operations implementations are already available and can be applied to an object during initialization:

Environment

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.

Events

Several objects will fire events to which can be subscribed:

The WireContext itself fires the EVENT_OPEN and EVENT_OPEN events.

The Descriptors will fire the events Descriptor.EVENT_CONSTRUCTING, Descriptor.EVENT_INITIALIZING, Descriptor.EVENT_CONSTRUCTED, Descriptor.EVENT_SET and Descriptor.EVENT_REMOVE.

And last but not least, the objects created by the WireContext can be Observable themselves.

Eager initialization

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.

Specifying how an object should be initialized.

The initialization can be specified with the AbstractDescriptor.setInit(char) method.

The possible value for init parameter is one of :

Author:
Tom Baeyens, Guillaume Porcher (documentation)
See Also:
Serialized Form

Field Summary
protected  java.lang.ClassLoader classLoader
           
protected  Environment environment
           
protected  EnvironmentFactory environmentFactory
           
static java.lang.String EVENT_CLOSE
          is fired when the wiring environment is being closed.
static java.lang.String EVENT_OPEN
          is fired when a new wiring environment is being opened.
protected  java.lang.String name
           
protected  WireDefinition wireDefinition
           
 
Fields inherited from class org.jbpm.util.DefaultObservable
listeners
 
Constructor Summary
WireContext()
           
WireContext(WireDefinition wireDefinition)
           
WireContext(WireDefinition wireDefinition, java.lang.String name, Environment environment, boolean delayCreate)
          allows for postponing the creation of this wire context.
WireContext(WireDefinition wireDefinition, java.lang.String name, EnvironmentFactory environmentFactory)
          when this Context is used in an Environment, it needs a name.
 
Method Summary
protected  void addException(Descriptor descriptor, java.lang.Exception exception)
           
 void clear()
          clears the cache.
 void close()
          fires the close event then removes the listeners, and cleans up the constructed objects of the context (cleans up the object in the cache and the object in construction).
 void create()
          initializes the eager objects and then fires the create event.
 java.lang.Object create(Descriptor descriptor, boolean isDelayable)
          creates a new object for the given descriptor.
protected  java.lang.Object create(java.lang.String objectName, boolean isDelayable)
          creates a new object for the given objectName as defined in the wireDefinition.
protected  void fireObjectEvent(java.lang.String eventName, java.lang.String objectName, java.lang.Object object)
          fires a WireObjectEventInfo.
<T> T
get(java.lang.Class<T> type)
          searches for the first descriptor that defines an object of the given type.
 java.lang.Object get(java.lang.String objectName)
          retrieves the object for the given objectName, ensuring it is constructed and initialized.
 java.lang.Object get(java.lang.String objectName, boolean isDelayable)
          gets the object having the name objectName in this context.
 java.lang.ClassLoader getClassLoader()
          the class loader to use to create objects or if none was explicitely set in this wire context, the default context class loader for the current thread.
 Environment getEnvironment()
           
 EnvironmentFactory getEnvironmentFactory()
           
 java.lang.String getName()
           
 WireDefinition getWireDefinition()
           
 boolean has(java.lang.String objectName)
          checks if the given objectName is defined, either by means of a descriptor or by an explicit set(String, Object).
 boolean hasCached(java.lang.String objectName)
          checks if the given objectName is available in the cache, which means it already has been constructed from a wire definition or it has been set(String, Object) explicitely.
 boolean hasClassLoader()
           
protected  boolean hasException(java.lang.String objectName)
           
 java.util.Set<java.lang.String> keys()
          the list of object names defined in this context.
 java.lang.Object remove(java.lang.String objectName)
          removes an object from the context and fires the remove event.
 java.lang.Object set(java.lang.String objectName, java.lang.Object object)
          adds an object to this context, which means storing it in the cache.
 void setClassLoader(java.lang.ClassLoader classLoader)
           
 void setEnvironment(Environment environment)
          invoked (with a non-null argument) by the environment when this context is added.
 void setWireDefinition(WireDefinition wireDefinition)
           
 java.lang.String toString()
           
 
Methods inherited from class org.jbpm.util.DefaultObservable
addListener, addListener, addListener, fire, fire, removeListener
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

EVENT_OPEN

public static final java.lang.String EVENT_OPEN
is fired when a new wiring environment is being opened. No event info provided.

See Also:
Constant Field Values

EVENT_CLOSE

public static final java.lang.String EVENT_CLOSE
is fired when the wiring environment is being closed. No event info provided.

See Also:
Constant Field Values

name

protected java.lang.String name

environment

protected Environment environment

environmentFactory

protected EnvironmentFactory environmentFactory

classLoader

protected transient java.lang.ClassLoader classLoader

wireDefinition

protected WireDefinition wireDefinition
Constructor Detail

WireContext

public WireContext()

WireContext

public WireContext(WireDefinition wireDefinition)

WireContext

public WireContext(WireDefinition wireDefinition,
                   java.lang.String name,
                   EnvironmentFactory environmentFactory)
when this Context is used in an Environment, it needs a name.


WireContext

public WireContext(WireDefinition wireDefinition,
                   java.lang.String name,
                   Environment environment,
                   boolean delayCreate)
allows for postponing the creation of this wire context.

Parameters:
delayCreate - specifies if creation should be postponed till create() is called explicitly. If delayCreate is set to false, creation is done as part of the constructor. If delayCreate is set to true, the create() method needs to be called explicitly by the client after construction is complete. The use case is creation of environment where the transactionName needs to be set and the scope needs to be added to the environment before the creation of this wire scope is done.
See Also:
DefaultEnvironmentFactory.openEnvironment()
Method Detail

create

public void create()
initializes the eager objects and then fires the create event. This method only needs to be called explicitly in case delayCreate is true in WireContext(WireDefinition, String, Environment, boolean).


setEnvironment

public void setEnvironment(Environment environment)

invoked (with a non-null argument) by the environment when this context is added.

When the context is removed from the environment, this method will be called again with the null value. In this case, the close() method is called to close the context.

Specified by:
setEnvironment in interface Context
See Also:
Context.setEnvironment(Environment)

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object

keys

public java.util.Set<java.lang.String> keys()
the list of object names defined in this context. This means the union of the object names that are defined in the wireDefinition and the objects that are just set(String, Object). If there are no keys, an empty set will be returned.

Specified by:
keys in interface Context

has

public boolean has(java.lang.String objectName)
checks if the given objectName is defined, either by means of a descriptor or by an explicit set(String, Object).

Specified by:
has in interface Context

get

public java.lang.Object get(java.lang.String objectName)
retrieves the object for the given objectName, ensuring it is constructed and initialized.

Specified by:
get in interface Context
Returns:
the object found, or null if the object was not found.

set

public java.lang.Object set(java.lang.String objectName,
                            java.lang.Object object)
adds an object to this context, which means storing it in the cache. This doesn't have to be an object that is defined by the WireDefinition. If an object is set under a certain objectName that also is associated with a descriptor, the object provided in this set invocation will be delivered upon subsequent get(String) requests.

Specified by:
set in interface Context
Returns:
previous value of the object with the name objectName in the cache
Throws:
WireException - when the objectName is null

remove

public java.lang.Object remove(java.lang.String objectName)
removes an object from the context and fires the remove event.

Returns:
previous object associated with the given name, or null if there was no mapping for this name.

clear

public void clear()
clears the cache.


close

public void close()
fires the close event then removes the listeners, and cleans up the constructed objects of the context (cleans up the object in the cache and the object in construction).

Specified by:
close in interface Closable
See Also:
EVENT_CLOSE

get

public java.lang.Object get(java.lang.String objectName,
                            boolean isDelayable)
gets the object having the name objectName in this context.

Parameters:
isDelayable - indicates wether initialization is delayable. When isDelayable is set to false the returned object will be constructed and initialized. When isDelayable is set to true, the returned object will be constructed, but not necessarily initialized.
Returns:
the object found or created, or null if the object was not found and cannot be created.
Throws:
WireException - if a circular dependency was found during the object creation.

create

protected java.lang.Object create(java.lang.String objectName,
                                  boolean isDelayable)
creates a new object for the given objectName as defined in the wireDefinition.

Parameters:
isDelayable - indicates wether initialization is delayable. When isDelayable is set to false the returned object will be constructed and initialized. When isDelayable is set to true, the returned object will be constructed, but not necessarily initialized.

create

public java.lang.Object create(Descriptor descriptor,
                               boolean isDelayable)
creates a new object for the given descriptor.

Parameters:
isDelayable - indicates wether initialization is delayable. When isDelayable is set to false the returned object will be constructed and initialized. When isDelayable is set to true, the returned object will be constructed, but not necessarily initialized.

hasCached

public boolean hasCached(java.lang.String objectName)
checks if the given objectName is available in the cache, which means it already has been constructed from a wire definition or it has been set(String, Object) explicitely.


fireObjectEvent

protected void fireObjectEvent(java.lang.String eventName,
                               java.lang.String objectName,
                               java.lang.Object object)
fires a WireObjectEventInfo.


getClassLoader

public java.lang.ClassLoader getClassLoader()
the class loader to use to create objects or if none was explicitely set in this wire context, the default context class loader for the current thread.


hasClassLoader

public boolean hasClassLoader()

get

public <T> T get(java.lang.Class<T> type)
searches for the first descriptor that defines an object of the given type. In case of multiple objects of the same type, the first object that is declared of the given type will be found. Also super classes and interfaces are taken into account. Not all descriptor types will be type sensitive, only:
 | ObjectDescriptor                       | object            |
 | HibernatePersistenceServiceDescriptor  | business-calendar |
 | TransactionDescriptor                  | transaction       |
 | PropertiesDescriptor                   | properties        |
 | BusinessCalendarDescriptor             | business-calendar |
 
 

Specified by:
get in interface Context

hasException

protected boolean hasException(java.lang.String objectName)

addException

protected void addException(Descriptor descriptor,
                            java.lang.Exception exception)

getName

public java.lang.String getName()
Specified by:
getName in interface Context

setClassLoader

public void setClassLoader(java.lang.ClassLoader classLoader)

getWireDefinition

public WireDefinition getWireDefinition()

setWireDefinition

public void setWireDefinition(WireDefinition wireDefinition)

getEnvironment

public Environment getEnvironment()

getEnvironmentFactory

public EnvironmentFactory getEnvironmentFactory()