felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From clem...@apache.org
Subject svn commit: r1478332 - in /felix/site/trunk: content/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/apache-felix-ipojo-instances.mdtext templates/ipojo.html
Date Thu, 02 May 2013 11:41:22 GMT
Author: clement
Date: Thu May  2 11:41:22 2013
New Revision: 1478332

URL: http://svn.apache.org/r1478332
Log:
new documentation about instance creation

Added:
    felix/site/trunk/content/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/apache-felix-ipojo-instances.mdtext
Modified:
    felix/site/trunk/templates/ipojo.html

Added: felix/site/trunk/content/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/apache-felix-ipojo-instances.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/apache-felix-ipojo-instances.mdtext?rev=1478332&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/apache-felix-ipojo-instances.mdtext
(added)
+++ felix/site/trunk/content/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/apache-felix-ipojo-instances.mdtext
Thu May  2 11:41:22 2013
@@ -0,0 +1,353 @@
+translation_pending: true
+Title: Creating instances
+
+# Creating instances
+
+[TOC]
+
+Component types and instances
+==============================
+
+iPOJO is a component model enforcing strictly the distinction between component types and
instances. The relationship between types and instances is the same as the one between classes
and objects in OOP. You can _instantiate_ as many instances as you want from a component type.
These instances can be configured with different properties. As a consequence, just using
@Component or <component/> declares a component type, not an instance. So, at runtime,
nothing will happen until you actually declare or create an instance.
+
+iPOJO provides several ways to create instances, this page presents these possibilities:
+
+* @Instantiate to create an instance directly from the a class annotated with @Component
+* @Configuration to declare a set of instances
+* using <instance> in the XML metadata
+* using the iPOJO Factory service
+* using the OSGi Configuration Admin
+
+
+@Instantiate
+============
+
+The @Instantiate annotation is the simplest way to declare an instance. In a class annotated
with @Component, you just add the @Instantiate annotation. It instructs iPOJO to declare an
instance of the component type described by the current class. 
+
+    :::java
+    import org.apache.felix.ipojo.annotations.Component;
+    import org.apache.felix.ipojo.annotations.Instantiate;
+        
+    @Component
+    @Instantiate
+    public class MyComponent {
+        //...
+    }
+
+Optionally, you can set the instance name, using the `name` attribute.
+
+    :::java
+    import org.apache.felix.ipojo.annotations.Component;
+    import org.apache.felix.ipojo.annotations.Instantiate;
+        
+    @Component
+    @Instantiate(name="myInstance")
+    public class MyComponent {
+        //...
+    }
+
+The @Instantiate annotation is easy to use but, has a couple of limitations:
+
+* it must be used in the @Component class
+* you can't provide a configuration to the instance
+* you can declare only one instance
+
+Declaring a singleton instance
+------------------------------
+
+The @Instance annotation is particularly useful to declare singleton instances, i.e. a component
type with only one instance. To create a singleton instance, combine the @Instantiate annotation
and the `publicFactory` attribute of the @Component annotation:
+
+    :::java
+    import org.apache.felix.ipojo.annotations.Component;
+    import org.apache.felix.ipojo.annotations.Instantiate;
+        
+    @Component(publicFactory=false)
+    @Instantiate
+    public class MySingleton {
+        //...
+    }    
+
+The `publicFactory=false` attribute makes the component type _private_, so invisible from
other bundles. No one else would be able to create another instance of the component type.
+
+@Configuration
+==============
+
+This second annotation is used on classes to create one or several instances using a fluent
API.
+
+    :::java
+  	import org.apache.felix.ipojo.configuration.Configuration;
+  	import org.apache.felix.ipojo.configuration.Instance;
+
+
+  	import static org.apache.felix.ipojo.configuration.Instance.instance;
+  	@Configuration
+  	public class ConfigureOneInstance {
+
+  	    Instance myInstance = instance().of(MyComponent.class)
+  	            .with("property").setto("value");
+  	}
+
+The class is annotated with @Configuration. All fields of type Instance (`org.apache.felix.ipojo.configuration.Instance`)
are read and declares an instance. In the previous example, an instance of the `MyComponent`
component type is declared with a property `property` set to `value`. The instance is named
`myInstance` (the field name).
+
+You can declare several instances in the same @Configuration class:
+
+    :::java
+  	@Configuration
+    public class ConfigureTwoInstances {
+
+      // Declare an instance of MyComponent named myInstance
+      Instance myInstance1 = instance().of(MyComponent.class)
+              .with("property").setto("value");
+
+      // Declare an instance of MyComponent
+      Instance myInstance2 = instance().of(MyComponent.class)
+              .with("property").setto("value2");
+
+      // Declare an instance of AnotherComponent
+      Instance myInstance2 = instance().of(AnotherComponent.class);
+  	}
+
+By default, the instance name is set to the field name. However, you can also set the instance
name:
+
+    :::java
+    // Declare an instance of MyComponent named hello
+    Instance myInstance2 = instance().of(MyComponent.class)
+            .named("hello")
+						.with("property").setto("value");
+
+Using this configuration DSL allows creating a set of instances that you can configure easily.
+
+Configuration including lists and maps
+--------------------------------------
+The `setto` method accepts any object. To ease creating collections, the API proposed two
methods to handle lists and maps:
+  
+    :::java
+    instance()
+		    .of(Mycomponent.class)
+    		// Lists	
+        .with("list").setto(list(1, 2, 3))
+        .with("list2").setto(list().with(1).with(2).with(3))
+        // Maps
+        .with("map").setto(map().with(pair("entry", "value")))
+				.with("map2")
+					.setto(map()
+						.with(entry("key", 1), entry("key2", 2)));
+
+Methods returning Instance objects
+----------------------------------
+
+The class annotated with @Configuration does not only handle fields, but also handles methods
returning Instance object. These methods can have either no arguments or the BundleContext
as unique argument.
+
+    :::java
+    Instance instance1() {
+        return instance().of(MyComponent.class);
+    }
+
+    Instance instance2(BundleContext bc) {
+        return instance().of(MyComponent.class);
+    }
+
+As for fields, the method name is used as instance name except if the instance already received
a name.
+
+_Note_: the injected BundleContext is the BundleContext of the bundle containing the annotated
class.
+
+Declaring instances in XML
+==========================
+
+You can declare instances using the iPOJO XML descriptor. If you use XML to describe you
component type, you probably want to use this way to create your instances.
+
+    :::xml
+		<instance component="factory.name">
+   		<property name="property" value="value"/>
+		  <property name="another property" value="another value"/>
+		</instance>
+
+The _component_ attribute specifies the targeted component type. Generally it's the qualified
classname of the component class, but can also be the name of the factory if one is specified.
+
+The _property_ elements have a mandatory `name` attribute to set the property name, and a
`value` attribute to specify the String form of the property's value.
+
+You can declare as many as you want instances in the XML descriptor. They can targets component
types declared within the same bundles or not.
+
+Setting the instance name
+-------------------------
+
+To set the instance name you can use the _name_ attribute of the _instance_ element or the
_instance.name_ property:
+
+    :::xml
+	<instance component="…MyComponent" name="my-instance"/>
+	<instance component="…MyComponent">
+		<property name="instance.name" value="my-instance-2"/>
+	</instance>
+
+Describing complex properties in XML
+------------------------------------
+
+The _property_ element can be used to configure complex types such as arrays, lists and maps.
+
+    :::xml
+    <!--Creates a string array-->
+  	<property name="array" type="array"> 
+	  	<property value="a"/>
+		  <property value="b"/>
+  	</property>
+    <!--Creates a list containing string-->
+  	<property name="list" type="list"> 
+	  	<property value="a"/>
+		  <property value="b"/>
+  	</property>
+    <!--Creates a dictionary containing string-->
+  	<property name="dict" type="dictionary">
+	  	<property name="a" value="a"/>
+		  <property name="b" value="b"/>
+  	</property>
+    <!--Creates a map containing string-->
+  	<property name="map" type="map"> 
+	  	<property name="a" value="a"/>
+		  <property name="b" value="b"/>
+  	</property>
+    <!--A complex type can contain 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"/>
+
+Creating instances using the Factory service
+============================================
+
+In previous technics to create instances were declarative. You declare an instance. This
instance is going to be created as soon as the component type becomes available, and disappears
as soon as the component type leaves. The technic presented here is a programatic way.
+
+Each (non private) component types are exposed as an OSGi service. You can use this OSGi
service to create, reconfigure and dispose instances from your code.
+
+The Factory service
+-------------------
+
+The published service interface is `org.apache.felix.ipojo.Factory` and provides the following
methods:
+
+    :::java
+    /**
+     * Creates an instance manager (i.e. component type instance).
+     * @param configuration the configuration properties for this component.
+     * @return the created instance manager.
+     * @throws UnacceptableConfiguration if the given configuration is not valid.
+     * @throws MissingHandlerException if an handler is missing.
+     * @throws ConfigurationException if the instance configuration failed.
+     */
+    ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration,
MissingHandlerException, ConfigurationException;
+
+    /**
+     * Reconfigures an instance already created. This configuration needs to
+     * have the name property to identify the instance.
+     * @param conf the configuration to reconfigure the instance. The instance.name property
must be set to identify the instance to reconfigure.
+     * @throws UnacceptableConfiguration  if the given configuration is not consistent for
the targeted instance.
+     * @throws MissingHandlerException if an handler is missing.
+     */
+    void reconfigure(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException;
+
+You can identify the factory using the _factory.name_. So target a specific component type,
use the following filter:
+
+    :::sh
+		(factory.name=...MyComponent)
+
+If you grab all factories, you can check their names using the `getName()` method.
+
+Creating instances
+------------------
+Once you have the right Factory service, you can create instances using `createComponentInstance`
method. This method returns a reference on the created instance. This method receives an optional
configuration containing key-value pairs. Values are either objects (of the adequate type)
or Strings used to create objects. This configuration can be 'null' if no properties have
to be pushed.
+
+You can set the instance name using the 'instance.name' property can be used to specify the
instance name.
+
+Instances are automatically started when created. However, the instance can be invalid, if
at least one handler is not valid. 
+
+The instance creation process can fail. Three exceptions can be thrown during the creation:
+
+* `UnacceptableConfiguration` means that mandatory properties are missing in the instance
configuration
+* `MissingHandlerException` means that the factory is not valid (i.e. an external handler
is missing)
+* `ConfigurationException` means that the instance configuration has failed. The cause can
be either an issue in the component type description or an invalid property type.
+
+If an error occurs, a comprehensive message is reported in order to solve the issue.
+
+The next snippet shows an example of instance creation:
+
+    :::java
+  	// 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 instance
+--------------------------
+You 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).
+
+    :::java
+	instance.dispose();
+
+Reconfiguring instance
+----------------------
+
+To 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.
+
+    :::java
+	Properties props2 = new Properties();
+	props2.put("foo", "abc");
+	instance.reconfigure(props2);
+
+Following the factory state
+---------------------------
+Factories can becomes invalid if one of the handler they require is not available. Basically,
handlers are pieces of iPOJO containers. 
+
+You can check the factory state using the `Factory.getState()` method. This method returns
`1` if the factory is valid, `0` if not.
+
+You can also register a `org.apache.felix.ipojo.FactoryStateListener` object on the factory
to be notified of the changes.
+
+Creating instances using the OSGi Configuration Admin
+=====================================================
+
+The configuration admin service is a standard service specified by the OSGi Alliance to handle
configurations. It allows an operator to configured the deployed bundles, and so iPOJO instances.

+
+iPOJO supports the configuration admin and you can create, reconfigure and dispose instanced
using this service.
+
+Creating instances
+------------------
+
+Creating an instance is done by creating a _factory_ configuration:
+
+    :::java
+	ConfigurationAdmin admin = ...// Let's assume with have the configuration admin
+	Configuration conf = admin.createFactoryConfiguration("...MyComponent", "?");	
+	
+	// Build the instance configuration
+	Dictionary dict = new Hashtable();
+	//...
+
+	// Push the configuration to the configuration admin
+	conf.update(dict);
+
+To create the _factory_ configuration, use the `createFactoryConfiguration` method on the
Configuration Admin object. The first argument is the factory name. The second is the location
binding. Using "?" is a wildcard, for more details, check the configuration admin specification.
+
+You populate this configuration with a dictionary. The configuration is actually created
using the `update` method. 
+
+Reconfiguring instances
+-----------------------
+If the instance was created using the Configuration Admin and you own the Configuration object
used for the creation, the reconfiguration is done by calling the `update` method with the
new properties.
+
+If the instance was already created, you can configure it using a _regular_ configuration.
The pid given to this configuration is the instance name.
+
+Disposing instances
+-------------------
+To dispose an instance, just call the `delete` method on the configuration object you used
to configure the instance.
+

Modified: felix/site/trunk/templates/ipojo.html
URL: http://svn.apache.org/viewvc/felix/site/trunk/templates/ipojo.html?rev=1478332&r1=1478331&r2=1478332&view=diff
==============================================================================
--- felix/site/trunk/templates/ipojo.html (original)
+++ felix/site/trunk/templates/ipojo.html Thu May  2 11:41:22 2013
@@ -83,6 +83,7 @@
                                 <li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/configuration-handler.html">Configuration</a></li>
                                 <li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/architecture-handler.html">Introspection</a></li>
                                 <li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/describing-components/controller-lifecycle-handler.html">Impacting
the lifecycle</a></li>
+                                <li><a href="/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/apache-felix-ipojo-instances.html">Creating
instances</a></li>
                                 <li class="divider"></li>
                                 <li class="dropdown-submenu">
                                     <a tabindex="-1" href="#">External <em>handlers</em></a>



Mime
View raw message