Include Page | ||||
---|---|---|---|---|
|
HTML |
---|
<div class="content">
|
Combining iPOJO and Configuration Admin
This page presents how creating, reconfiguring and destroying iPOJO component instance with the OSGi Configuration Admin.
Div | ||||||
---|---|---|---|---|---|---|
| ||||||
|
Configuration Admin
The Configuration Admin service is a configuration manager describe in the OSGi R4 Compendium. It allows an operator to set the configuration information of deployed applications . The Configuration Admin defines the Configuration as the process of defining the configuration data of applications and assuring that those applications receive that data when they are running. The Configuration Admin is becoming an important piece on OSGi Gateway. It is become the standard way to configure applications on OSGi gateways.
Why using Configuration Admin with iPOJO
As the configuration admin offer an administration support, it seems reasonable to combine iPOJO and the Configuration Admin to control the gateway. Indeed, thanks to the configuration admin it should be possible to:
- Create new component instances
- Configuring / Reconfiguring reconfiguring these instances
- Destroying these instances instances
- Reconfiguring instances by using Managed Services (not addressed in this page, see here for further information)
The configuration admin is persistent, so stored configuration will be reload it the framework restarts.
Moreover, using the configuration admin allows avoiding describing instances inside iPOJO metadata file. These instances are created by inserting new configurations in the configuration admin.
Combining iPOJO and the Configuration Admin
iPOJO has a component type concept. For each (public) component type, a ManagedServiceFactory
is published. For each configurations matching with the component type from the Configuration Admin, a new component instance is created. Moreover, when this configuration is updated, the instance is dynamically reconfigured. If the configuration is removed, the instance is disposed.
...
- If the factory is available or an instance is create immediately,
- Else the factory is not available and the instance will be created as soon as the factory appears.
Examples
This section presents 3 examples about the management of iPOJO instances with the configuration admin:
...
All these examples are downloadable here
Prerequisites
. The archive contains both the project sources and a pre-configured version of felix.
To compile the project, launch ant from the config.admin.tutorial directory
Then, you can launch Felix by launching the following command from the felix
directory:
Code Block |
---|
Java -jar bin/felix.jar
|
Prerequisites
LetLet's take 4 Felix shell commands to manage configuration admin configurations (available in the example archive):
- Create
create_conf <type> <property-key=property-value>*
allows to create a new Factory Configuration attached to the given type. The configuration contains the given properties. - Update
update_conf <configuration_name> < property-key=property-value>*
allows to update the configuration with the given name with the given properties. - Delete
delete_conf <configuration_name>
allows deleting the configuration with the given name. If the name is 'all', delete all stored configurations. - List
list_conf
allows listing all stored configuration.
...
Code Block |
---|
-> ps START LEVEL 1 ID State Level Name [ 0] [Active ] [ 0] System Bundle (0.91.0.incubator-SNAPSHOT3) [ 1] [Active ] [ 1] Apache Felix Shell Service (1.0.9.0.incubator_SNAPSHOT) [ 2] [Active ] [ 1] Apache Felix Shell TUI (1.0.9.0.incubator_SNAPSHOT) [ 3] [Active ] [ 1] Apache Felix Bundle Repository (01.9.0.incubator_SNAPSHOT2) [ 4] [Active ] [ 1] Apache Felix Configuration Admin Service (01.9.0.incubator_SNAPSHOT10) [ 5] [Active ] [ 1] Apache Felix iPOJO (01.7.1.incubator_SNAPSHOT)2.0) [ 6] [Active ] [ 1] OSGiApache R4Felix CompendiumiPOJO BundleArch (4) [ 7] [Active ] [ 1] javax.servlet-2.3 (0)Command (1.2.0) |
Simple Instantiation
Imagine the following dummy very simple component implementation:
Code Block | ||||
---|---|---|---|---|
| ||||
public class Hello1 { public Hello1() { System.out.println("Hello"); } } |
The component type is defined with following metadata:
Code Block | ||||
---|---|---|---|---|
| ||||
<component classname="org.apache.felix.ipojo.example.ca.component.Hello1" factory="hello1" immediate="true" architecture="true"/> |
The defined component type (Hello1) just creates a Hello1 object when the instance is created (thanks to the immediate attribute).
So if we deploy this bundle and add a consistent configuration we obtain :(note that bundle need to be already compiled):
Code Block |
---|
-> start file:/F:\dev\workspaces\iPOJO_dev\ConfigAdminExample\ConfigAdminExample..\config.admin.tutorial\output\config.admin.tutorial.jar -> create_conf hello1 org.apache.felix.ipojo.example.ca.component.Hello1 Insert the configuration : {service.factoryPid=hello1} Hello org.apache.felix.ipojo.example.ca.component.Hello1} -> Hello |
Note: Debug messages from the configuration admin were removed
So as predicted, the Hello message appears. To be really sure of the creating, we can ask for the instance architecture (the component type allows architecture introspection thank to the architecture attribute):
Code Block |
---|
-> arch Instance hello1.02f683ef-85b2-44fc-8ef5-719d40557c07ArchCommand -> valid -> -> arch hello1.02f683ef-85b2-44fc-8ef5-719d40557c07 instance name="hello1.02f683ef-85b2-44fc-8ef5-719d40557c07" state="valid" bundle="8" component.type="hello1" handler name="Instance org.apache.felix.ipojo.example.ca.component.Hello1.e40fe80a-2c0d-4c51-b00b-a82565874cd8 -> valid -> -> arch -instance org.apache.felix.ipojo.handlersexample.ca.lifecyclecomponent.callback.LifecycleCallbackHandler" state="valid" handler name=Hello1.e40fe80a-2c0d-4c51-b00b-a82565874cd8 instance name= "org.apache.felix.ipojo.example.handlersca.component.architecture.ArchitectureHandler" state="valid" Hello1.e40fe80a-2c0d-4c51-b00b-a82565874cd8" component.type="hello1" state="valid" bundle="7" object name="org.apache.felix.ipojo.example.ca.component.Hello1@16925b0Hello1@120cc56" -> |
So, the instance is correctly created. The name of the instance was created from the given one by the configuration admin. It could change according to your configuration admin implementation.
Note : The arch command is available on the Felix trunk
Then, we can delete the instance by removing the configuration from the configuration admin:
Code Block |
---|
-> delete_conf hello1.02f683ef-85b2-44fc-8ef5-719d40557c07
Delete the configuration : hello1.02f683ef-85b2-44fc-8ef5-719d40557c07
-> arch
->
|
So, arch does no more displayed any instance, the created instance was disposed.
Reconfiguring instances with the Configuration Admin
Imagine the following component implementation:
handler
name="org.apache.felix.ipojo.handlers.lifecycle.callback.LifecycleCallbackHandler"
state="valid"
handler
name="org.apache.felix.ipojo.handlers.architecture.ArchitectureHandler"
state="valid"
->
|
So, the instance is correctly created. The name of the instance was created by the configuration admin. It could change according to your configuration admin implementation.
Then, we can delete the instance by removing the configuration from the configuration admin:
Code Block |
---|
-> delete_conf
org.apache.felix.ipojo.example.ca.component.Hello1.e40fe80a-2c0d-4c51-b00b-a82565874cd8
Delete the configuration :
org.apache.felix.ipojo.example.ca.component.Hello1.e40fe80a-2c0d-4c51-b00b-a82565874cd8
-> arch
Instance ArchCommand -> valid
|
So, arch does no more displayed any hello instances, the created instance was disposed.
Reconfiguring instances with the Configuration Admin
Imagine the following component implementation:
Code Block | ||||
---|---|---|---|---|
| ||||
public class Hello2 {
String m_name;
public void stop() {
System.out.println("Good by | ||||
Code Block | ||||
public class Hello2 {
String m_name;
public void stop() {
System.out.println("Good by " + m_name);
}
public void setName(String newName) {
m_name = newName;
System.out.println("Hello " + m_name);
}
|
And the following metadata:
Code Block |
---|
<component classname="org.apache.felix.ipojo.example.ca.component.Hello2" factory="hello2" immediate="true" architecture="true">
<callback initial="VALID" final="INVALID" method="stop"/>
<properties>
<property field="m_name" name="to" method="setName"/>
</properties>
</component>
|
The defined component type (Hello2) write "Hello + $name" when the property 'to' (attached to the field _m_name_) receive a new value. A value is necessary insert in the instance configuration. Moreover when killed, the instance will display a "Good By" message.
Let's play a simple scenario:
- Create an Hello2 instance
- Update the instance configuration
- Kill the created instance
public void setName(String newName) {
m_name = newName;
System.out.println("Hello " + m_name);
}
|
And the following metadata:
Code Block | ||||
---|---|---|---|---|
| ||||
<component
classname="org.apache.felix.ipojo.example.ca.component.Hello2"
factory="hello2" immediate="true" architecture="true">
<callback transition="validate" method="stop"/>
<properties>
<property field="m_name" name="to" method="setName"/>
</properties>
</component>
|
The defined component type (Hello2) write "Hello + $name" when the property 'to' (attached to the field m_name) receive a new value. A value is necessary insert in the instance configuration. Moreover when killed, the instance will display a "Good By" message.
Let's play a simple scenario:
- Create a Hello2 instance
- Update the instance configuration
- Kill the created instance
Code Block |
---|
-> create_conf org.apache.felix.ipojo.example.ca.component.Hello2 to=ipojo
Insert |
Code Block |
-> create_conf hello2 to=clement Insert the configuration : {service.factoryPid=hello2, to=clement} Hello clement -> list_conf hello2.e41713c3-9ff8-4bbb-a128-97d267962e58 : {service.pid=hello2.e41713c3-9ff8-4bbb-a128-97d267962e58, service.factorypid=hello2, to=clement} -> update_conf hello2.e41713c3-9ff8-4bbb-a128-97d267962e58 to=Rick Update the configuration : {service.pid=hello2.e41713c3-9ff8-4bbb-a128-97d267962e58, service.factorypid=hello2factoryPid=org.apache.felix.ipojo.example.ca.component.Hello2, to=Rickipojo} Hello Rick -> delete_conf hello2.e41713c3-9ff8-4bbb-a128-97d267962e58 Delete the configuration : hello2.e41713c3-9ff8-4bbb-a128-97d267962e58 Good by Rick |
In this simple scenario, we see that when updated the attached configuration, the instance receives the new value. The setName method is immediately invoked to inject the new value. Moreover, when the configuration is deleted, the instance is going to be killed: the "Good Bye" message appears and the instance is disposed.
Obviously it is possible to create several instance of the same type :
Code Block |
---|
-> create_conf hello2 to=clement
Insert the configuration : {service.factoryPid=hello2, to=clement}
Hello clement
-> create_conf hello2 to=rick
Insert the configuration : {service.factoryPid=hello2, to=rick}
Hello rick
-> arch
Instance hello2.3d64ae54-98ae-43f4-845a-15956b2a78ce -> valid
Instance hello2.b5e3fc82-25bf-4191-bb56-f5afe516e2fa -> valid
|
The 'arch' command displays the two created instances.
Property Propagation
It is possible to propagate the instance configuration to the published service properties. To activate property propagation you need to write the 'configurable' attribute in the 'properties' element as in
Created configuration:
org.apache.felix.ipojo.example.ca.component.Hello2.75082279-9b4b-4c49-b0e0-8efb38b67aa3
Hello ipojo
-> list_conf
org.apache.felix.ipojo.example.ca.component.Hello2.75082279-9b4b-4c49-b0e0-8efb38b67aa3 :
{service.pid=org.apache.felix.ipojo.example.ca.component.Hello2.75082279-9b4b-4c49-b0e0-8efb38b67aa3,
service.factorypid=org.apache.felix.ipojo.example.ca.component.Hello2,
to=ipojo}
-> update_conf
org.apache.felix.ipojo.example.ca.component.Hello2.75082279-9b4b-4c49-b0e0-8efb38b67aa3 to=felix
Update:
pid=org.apache.felix.ipojo.example.ca.component.Hello2.75082279-9b4b-4c49-b0e0-8efb38b67aa3
Update the configuration : {to=felix}
Hello felix
-> delete_conf
org.apache.felix.ipojo.example.ca.component.Hello2.75082279-9b4b-4c49-b0e0-8efb38b67aa3
Delete the configuration :
org.apache.felix.ipojo.example.ca.component.Hello2.75082279-9b4b-4c49-b0e0-8efb38b67aa3
Good by felix-> list_conf
|
In this simple scenario, we see that when the configuration is updated, the instance receives the new value. The setName method is immediately invoked to inject the new value. Moreover, when the configuration is deleted, the instance is going to be killed: the "Good Bye" message appears and the instance is disposed.
Obviously it is possible to create several instance of the same type:
Code Block |
---|
-> create_conf |
Code Block |
<component classname="org.apache.felix.ipojo.example.ca.component.Hello3"Hello2 factoryto="hello3" architecture="true"> <provides/> <properties configurable="true"> <property field="m_name" value="clement"/> </properties> </component> |
The defined type provides a service. Moreover it supports properties propagation. So all property, except listed one (m_name), will be published inside the provided services.
Imagine that we have created an instance of the previous component. Service information about this instance are:
Code Block |
---|
factory.pid = hello3 objectClass =ipojo Insert the configuration : {service.factoryPid=org.apache.felix.ipojo.example.ca.component.Hello2, to=ipojo} Hello ipojo -> create_conf org.apache.felix.ipojo.example.ca.component.Hello2 to=felix Insert the configuration : {service.factoryPid=org.apache.felix.ipojo.example.ca.component.Hello2, to=felix} Hello felix -> arch Instance ArchCommand -> valid Instance org.apache.felix.ipojo.example.ca.servicecomponent.Hello service.factoryPid = hello3 service.id = 287 service.pid = hello3.e964c4e0-029f-4e49-a7cd-a4d8880f20c1 |
Now, we update the instance configuration with a new property 'p1':
Code Block |
---|
-> update_conf hello3.e964c4e0-029f-4e49-a7cd-a4d8880f20c1 p1=v1
Update the configuration : {p1=v1}
-> Remove : {service.pid=hello3.e964c4e0-029f-4e49-a7cd-a4d8880f20c1, service.factoryPid=hello3}
-> services 8
ConfigAdminExample (8) provides:
----
factory.pid = hello3
objectClass = org.apache.felix.ipojo.example.ca.service.Hello
p1 = v1
service.factoryPid = hello3
service.id = 287
service.pid = hello3.e964c4e0-029f-4e49-a7cd-a4d8880f20c1
|
Hello2.aaf1927c-1a81-490d-bd7b-21b13d454987 -> valid
Instance org.apache.felix.ipojo.example.ca.component.Hello2.9344fdbe-c35e-4afc-b839-f7ad0ea59a9d -> valid
|
The 'arch' command displays the two created instances.
Info | ||
---|---|---|
| ||
you can delete all created configurations with the delete_conf all command |
Property Propagation
It is possible to propagate the instance configuration to the published service properties. To activate property propagation you need to write the 'propagation' attribute in the 'properties' element as in
Code Block | ||||
---|---|---|---|---|
| ||||
<component
classname="org.apache.felix.ipojo.example.ca.component.Hello3"
factory="hello3" architecture="true">
<provides/>
<properties propagation="true">
<property field="m_name" value="clement"/>
</properties>
</component>
|
The defined type provides a service. Moreover it supports properties propagation. So all property, except listed one (m_name), will be published inside the provided services.
So create an instance of the Hello3 component type as followRemark that the new property p1 is published.
Now we can remove this property by reconfiguring the instance with an empty configuration:
Code Block |
---|
-> updatecreate_conf hello3.e964c4e0-029f-4e49-a7cd-a4d8880f20c1 Update org.apache.felix.ipojo.example.ca.component.Hello3 Insert the configuration : {service.factoryPid=org.apache.felix.ipojo.example.ca.component.Hello3} |
Then, you can check provided services with the services 7 command
Code Block |
---|
-> services 8 ConfigAdminExample (8) provides:7 // Factories and Managed Service factories // ---- factory.pidname = hello3 objectClass = org.apache.felix.ipojo.example.ca.service.Hello service.factoryPid = hello3 service.id = 287 service.pid = hello3.e964c4e0-029f-4e49-a7cd-a4d8880f20c1 |
The service does no more publish the p1 property.
Conclusion
...
org.apache.felix.ipojo.example.ca.component.Hello3
instance.name =
org.apache.felix.ipojo.example.ca.component.Hello3.a5ca5901-6e20-4636-8805-fbca2db1d68b
objectClass = org.apache.felix.ipojo.example.ca.service.Hello
service.factoryPid = org.apache.felix.ipojo.example.ca.component.Hello3
service.id = 69
->
|
Now, we update the instance configuration with a new property 'p1':
Code Block |
---|
-> update_conf
org.apache.felix.ipojo.example.ca.component.Hello3.a5ca5901-6e20-4636-8805-fbca2db1d68b p1=v1
Update the configuration : {p1=v1}
-> services 7
config.admin.tutorial (7) provides:
// Factories and Managed Service factories //
----
factory.name = org.apache.felix.ipojo.example.ca.component.Hello3
instance.name =
org.apache.felix.ipojo.example.ca.component.Hello3.a5ca5901-6e20-4636-8805-fbca2db1d68b
objectClass = org.apache.felix.ipojo.example.ca.service.Hello
p1 = v1
service.factoryPid = org.apache.felix.ipojo.example.ca.component.Hello3
service.id = 69
|
Remark that the new property p1 is published.
Now we can remove this property by reconfiguring the instance with an empty configuration:
Code Block |
---|
-> update_conf
org.apache.felix.ipojo.example.ca.component.Hello3.a5ca5901-6e20-4636-8805-fbca2db1d68b
Update the configuration : {}
-> services 7
ConfigAdminExample (8) provides:
// Factories and Managed Service factories //
----
factory.name = org.apache.felix.ipojo.example.ca.component.Hello3
instance.name =
org.apache.felix.ipojo.example.ca.component.Hello3.a5ca5901-6e20-4636-8805-fbca2db1d68b
objectClass = org.apache.felix.ipojo.example.ca.service.Hello
service.factoryPid = org.apache.felix.ipojo.example.ca.component.Hello3
service.id = 69
|
The service does no more publish the p1
property.
Conclusion
This page has presented how to combine the configuration admin and iPOJO. You can also use FileInstall in combination with iPOJO and the Configuration Admin. Subscribe to the Felix users mailing list by sending a message to users-subscribe@felix.apache.org; after subscribing, email questions or feedback to users@felix.apache.org
Include Page | ||||
---|---|---|---|---|
|