iPOJO Factories PrinciplesiPOJO defines a factory for each declared component type. These factories are used to create component instances. This document presents how to declare instances inside iPOJO metadata, and how-to create, dispose and reconfigure dynamically instances. Note: This page refers on iPOJO 0.8.0 and iPOJO 0.9.0-SNAPSHOT features. Preliminary ConceptsComponent TypeA component type is a kind of instance template. If we compare component concepts with object oriented programming, component types are classes and component instances are objects. A component type is declared inside a metadata file (generally named 'metadata.xml'). The next snippet shows you a component type declaration: <component className="..." name="MyFactory"> ... <!--component type configuration --> ... </component> A component type declaration begins generally by '<component>' and is composed by:
The 'name' attribute contains the factory name. If not specified, the 'className' attribute is used as the factory name. This factory name is used to refer to the factory (and consequently to the component type). <component className="..." name="MyPrivateFactory" public="false"> ... <!--component type configuration --> ... </component> Public factories offer different way to create instances:
Indeed, iPOJO will publish two services to access to the factory through the API:
The factory name will be used a service.pid property for these services. The service.pid is unique and persists between framework restarts. The service.pid of the factory equals the factory name. Component InstanceA component instance is an instance of a component type. For example, if a component type declares providing and requiring services, the component instances, will expose and require really those services. Several instances can be created from one factory, but all these instances will be managed as different entities, and so are independent. A component instance is characterized by:
A factory keeps a reference on each created instances. If the factory stops, goes away, or becomes invalid, all created instances are stopped and are destroyed.
How-to declare instances inside metadata filesThe main way to create instances is to declare those instances inside the iPOJO descriptor file (i.e. 'metadata.xml'). Those declarations can use either public factories from any bundle, or private factories from the same bundle. Private factories are generally used to guaranty singleton instance as instances can only be created inside the same bundle. <instance component="component factory name" name = "instance name" > <property name="a property name" value="a string form of the value"/> <property name="another prop name" value="the string form value "/> </instance> An instance declaration must contain the 'component' attribute. This attribute specifies the factory name (i.e. the component type). It can use either the factory name or the class name. The 'name' attribute allows setting the instance name. If not set, iPOJO will generate a unique name for you. Then, instances can declare properties. Those property are mostly key-value pair. The key refer to a property name from the component type declaration such as in: <component className="..." name="my-factory"> <properties> <property name="foo" field="m_foo"/> </properties> </component> <instance component="my-factory "> <property name="foo" value="bla bla bla"/> </instance> The string-form of the property value will be use to create the real object at runtime. If an unacceptable configuration is set, the instance is not created, and an error message appears to the console (and in the Log Service if present). <instance component="a.factory" name="complex-props"> <property name="array" type="array"> <!--Creates a string array--> <property value="a"/> <property value="b"/> </property> <property name="list" type="list"> <!--Creates a list containing string--> <property value="a"/> <property value="b"/> </property> <property name="dict" type="dictionary"> <!--Creates a dictionary containing string--> <property name="a" value="a"/> <property name="b" value="b"/> </property> <property name="map" type="map"> <!--Creates a map containing string--> <property name="a" value="a"/> <property name="b" value="b"/> </property> <!--A complex type can contains any other complex objects:--> <property name="complex-array" type="array"> <property type="list"> <property value="a"/> <property value="b"/> </property> <property type="list"> <property value="c"/> <property value="d"/> </property> </property> <!--Empty structures will create empty objects--> <property name="empty-array" type="array"/> <property name="empty-list" type="list"/> <property name="empty-map" type="map"/> </instance> Note: The 'instance.name' and 'factory.name' property should not be set directly. iPOJO will manage those properties. The 'instance.name' is created from the 'name' attribute of the instance declaration. Creating, disposing and reconfiguring instances with the APIA public factory is accessible through an exposed service (org.apache.felix.ipojo.Factory <component classname="..."> <requires field="a_field" filter="(factory.name=factory-name)"/> <requires field="another_field" from="another-factory"/> </component> Creating instancesOnce you have a reference on the factory you can create instance with the 'createComponentInstance' method. ComponentInstance createComponentInstance(java.util.Dictionary configuration)
throws UnacceptableConfiguration,
MissingHandlerException,
ConfigurationException
This method returns a reference on the created instance. As you see, the method receives a dictionary containing the instance configuration. This configuration contains key-value pairs. However, values are either object (of the adequate type) of String used to create objects. This configuration can be 'null' if no properties have to be pushed. Note: The 'instance.name' property can be used to specify the instance name.
If an error occurs, a comprehensive message is reported in order to solve the issue. // Assume we get a Factory in the fact field Properties props = new Properties(); props.put("instance.name","instance-name"); props.put("foo", "blablabla"); try { instance = fact.createComponentInstance(props); } catch(Exception e) { fail("Cannot create the instance : " + e.getMessage()); } Disposing created instanceYou can only disposed instances that you created. To dispose an instance, just call the 'dispose' method on the ComponentInstance object (returned by the createComponentInstance method). instance.dispose(); Reconfiguring instanceTo reconfigure an instance, call the 'reconfigure' method on the ComponentInstance object. This method receives the new set of properties. Be aware that the 'instance.name' property cannot be changed. Properties props2 = new Properties(); props2.put("foo", "abc"); instance.reconfigure(props2); How to use the ManagedServiceFactory to create, disposed and reconfigure instancesThe principle of the ManagedServiceFactory is the same as the iPOJO Factory Service. So, you can create, dispose and reconfigure instances with the Configuration Admin. For further information, read the OSGi R4 Compendium - Configuration Admin chapter. |
OverviewGetting StartedUser GuideToolsDeveloper GuideMisc & Contact
|

