hivemind.BuilderFactory Service
The BuilderFactory service is a service implementation factory ... a service that is used to construct other services.
The builder factory takes a single parameter element (usually with nested elements):
<construct class="..." autowire-services="..." log-property="..." messages-property="..." service-id-property="..." initialize-method="..." error-log-property="..." error-handler-property="..." class-resolver-property="..."> <log/> <messages/> <service-id/> <error-handler/> <error-log/> <class-resolver/> <string> ... </string> <boolean> ... </boolean> <configuration> ... </configuration> <int> ... </int> <long> ... </long> <resource> ... </resource> <service> ... </service> <object> ... </object> <null/> <event-listener service-id="..." event-type-name="..."/> <set property="..." value="..."/> <set-configuration property="..." configuration-id="..."/> <set-resource property="..." path="..."/> <set-service property="..." service-id="..."/> <set-object property="..." value="..."/> </construct>
The attributes of the construct element are used to specify the implementation class and set common service properties. Nested elements supply the constructor parameters and configure other specific properties of the implementation (the set-... elements).
construct
Attribute | Required ? | Description |
---|---|---|
autowire-services | no | If true (the default), then the BuilderFactory will attempt to automatically wire services and some common properties to constructor parameters and to properties of the constructed implementation with setter methods (see notes below). |
class | yes | The fully qualified name of the class to instantiate. |
class-resolver-property | no | The property to receive the module's ClassResolver. |
error-handler-property | no | The name of a property to recieve the module's ErrorHandler instance (which is used to report recoverable errors). |
error-log-property | no | The name of a property which will be assigned an ErrorLog instance for the service. An ErrorLog is simply a wrapper around a Log and an ErrorHandler as is the preferred approach. |
initialize-method | no | The name of a method (public, no parameters) to invoke after the service is constructed, to allow it to perform any final initializion before being put into use. |
log-property | no | The name of a property which will be assigned a org.apache.commons.logging.Log instance for the service. The Log is created from the complete service id (not the name of the class). If ommitted (and autowiring is disabled), no Log will be assigned. |
messages-property | no | Allows the Messages for the module to be assigned to a property of the instance. |
service-id-property | no | Allows the service id of the constructed service to be assigned to a property of the service implementation. |
The remaining elements are enclosed by the <construct> element, and are used to supply constructor parameters and configure properties of the constructed service implementation.
Autowiring
With autowire-services set to true the BuilderFactory can automatically both perform constructor based and setter based dependency injection. It will not only attempt to inject services but also certain common properties. By using standard names (and standard types), the need to specify attributes log-property, error-handler-property, etc. is avoided. Simply declaring a constructor parameter with the correct type or a writable property with the correct name and type is sufficient:
Property name | Property / parameter type | |
---|---|---|
classResolver | ClassResolver | |
errorHandler | ErrorHandler | |
errorLog | ErrorLog | |
log | org.apache.commons.logging.Log | |
messages | Messages | |
serviceId | String |
As noted the BuilderFactory will also inject services into the constructed service implementation. Through every constructor parameter and writable property whose type is an interface (with the exception of the common parameters / properties listed above) and hasn't been set otherwise the BuilderFactory will attempt to inject a service. This attempt may fail if there is no visible service or more than one visible service implementing the given interface. (Visibility is checked with respect to the module declaring the constructed service's implementation.)
The action taken if the service injection fails (due to one of the reasons given above) depends on the type of dependency injection. For constructor based dependency injection the BuilderFactory will try using a different constructor (see selection details below). If no "working" constructor is found an error is logged. For setter based dependency injection the BuilderFactory will log an error immedeately upon failed injection.
Constructor based dependency injection is enabled with the autowire-services attribute but can be overridden by declaring any constructor parameter elements (see next section). The constructor being used for the constructor based dependency injection has to meet all of the following criteria:
- the constructor is declared as public
- all parameter types are interfaces (including the common types listed above)
- no two parameters are of the same type
All constructors of the service implementation class meeting these criteria (the default constructor is considered as one of these) are ordered by length (given by the number of parameters) and the first of these for which every parameter type either has a matching common property or there is exactly one corresponding visible service available will be invoked. If no such constructor can be found an error is logged.
Autowiring may be complicated by the fact that one module may define a service point that will tangentially affect the construction of a service in another module (simply by implementing the same service interface). In this situation, service autowiring can be turned off, by setting the autowire-services attribute to false.
Once all properties have been set (possibly by autowiring), an initializer method will be invoked. If the initialize-method attribute is not specified, and the service implementation includes a public method initializeService() (no parameters, returns void), then initializeService() will be invoked as the initializer.
Constructor Parameter Elements
The following table summarizes the elements which can be used to specify constructor parameters for the class to instantiate. These elements can be mixed freely with the properties configuring elements. It is important to know that the number, type, and order of the constructor parameter elements determine the constructor that will be used to instantiate the implementation.
Element | Matched Parameter Type | Passed Parameter Value |
---|---|---|
error-handler | ErrorHandler | The module's ErrorHandler, user to report recoverable errors. |
error-log | ErrorLog | The service's ErrorLog, used to report recoverable errors (this is preferred over using a Log and an ErrorHandler). |
log | org.apache.commons.logging.Log | The Log is created from the complete service id (not the name of the class) of the created service. |
messages | Messages | The Messages object of the invoking module. |
object | variable | As determined by the object translator, this is decidedly free-form. See hivemind.ObjectProviders. |
null | any reference type | Always simply null. |
service-id | java.lang.String | The service id of the constructed service. |
string | java.lang.String | This element's content. |
boolean | boolean | This element's content. Must be either "true" or "false". |
configuration | java.util.List or java.util.Map | The List / Map of the elements of the configuration specified by this element's content as a configuration id. The id can either by a simple id for a configuration within the same module as the constructed service, or a complete id. |
int | int | This element's content parsed as an integer value. |
long | long | This element's content parsed as a long value. |
resource | Resource | This element's content parsed as a path to a Resource, which is relative to the contributing module's deployment descriptor. If available, a localized version of the Resource will be selected. |
service | interface corresponding to specified service | The implementation of the service with the id given in this element's content. The id can either be a simple id for a service within the same module as the constructed service, or a complete id. |
Service Property Configuring Elements
event-listener
Attribute | Description |
---|---|
service-id | The service which produces events. The service must provide, in its service interface, the necessary add and remove listener methods. |
name | The name of an event set to be registered. If not specified, all applicable event sets are used. |
If the name attribute is not specified, then BuilderFactory will register for all applicable event sets. For each event set provided by the specified service, BuilderFactory will check to see if the service instance being constructed implements the corresponding listener interface ... if so, the constructed service instance is added as a listener. When the name attribute is specified, the constructed service instance is registered as a listener of just that single type.
Event notifications go directly to the constructed service instance; they don't go through any proxies or interceptors for the service. The service instance must implement the listener interface, the constructed service's service interface does not have to extend the listener interface. In other words, event notifications are "behind the scenes", not part of the public API of the service.
It is perfectly acceptible to include multiple <event-listener> elements for a number of different event producing services.
It is not enough for the event producer service to have an add listener method (i.e., addPropertyChangeListener(PropertyChangeListener)). To be recognized as an event set, there must also be a corresponding remove listener method (i.e., removePropertyChangeListener(PropertyChangeListener)), even though BuilderFactory does not make use of the remove method. This is an offshoot of how the JavaBeans API defines event sets.
set
Attribute | Description |
---|---|
property | The name of the property to set. |
value | A value to assigned to the property. The value will be converted to an appropriate type for the property. |
set-configuration
Attribute | Description |
---|---|
property | The name of the property to set. |
configuration-id | The id of a configuration, either a simple id for a configuration within the same module as the constructed service, or a complete id. The property will be assigned a List or Map of the elements of the configuration. |
set-object
Attribute | Description |
---|---|
property | The name of the property to set. |
value | The selector used to find an object value. The selector consists of a prefix (such as "service" or "configuration"), a colon, and a locator whose interpretation is defined by the prefix. For example, service:MyService. See hivemind.ObjectProviders. |
set-resource
Attribute | Description |
---|---|
property | The name of the property to set. |
path | The path to a Resource, relative to the contributing module's deployment descriptor. If available, a localized version of the Resource will be selected. |
set-service
Attribute | Description |
---|---|
property | The name of the property to set. |
service-id | The id of a service, either a simple id for a service within the same module as the constructed service, or a complete id. The property will be assigned the service. |