Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

iPOJO is a service component model aiming to simplify OSGiâ„¢ applications development. iPOJO is based on the POJO concepts. A POJO is a simple Java class without any dependency on its runtime environment. In iPOJO, POJO are encapsulated in a container managing the relation between the POJO and the external world. This container keeps separate the POJO from the external world. Moreover, this container is flexible and extensible.
Basically, iPOJO contains two main concepts: Component Type and Component Instance. A component type is a type of component. A component type defines its implementation class, its creation policy, and its container. A component instance is a configured instance of a component type. This instance is created with the component type factory. A component instance inherits of all component type characteristics but has a unique name, and owns a configuration (set of <key, value>).
Above these concepts, iPOJO runtime will manage component type factories and component instances. Each component instance is managed separately. (but the factory can delete them).
A component type declares its container configuration. Each component instance owns its container conform to the component type container configuration. An iPOJO container is composed by an "InstanceManager", encapsulating the POJO, on which are plugged Handlers. A handler manages one non functional concern. Handlers participate to the component instance lifecycle; can interact with the POJO; can manage relations with external entity like database, or other POJOs ...
iPOJO is an extensible model allowing developer to manage other non functional concerns. Indeed, handlers can be developed singly, without modifying the iPOJO core. At runtime, iPOJO will look for each handler needed by a component instance and plug an instance of each (needed) handler on the container. So iPOJO containers are flexible, light and adaptable to each component. When a needed handler cannot be found, the component instance management failed.
An external handler is identified by a Namespace. This namespace matches with the class name (qualified name) implementing the handler behavior. This namespace will be used by developers to refer to the external handler (when he configures its component type) and by iPOJO to instantiate the handler object.

...

  • The Configure method is called when the component instance is created. The configure method have three parameters: the instance manager representing the component instance, the component type metadata and the component instance configuration. Inside the Configure method, the handler needs to look for its metadata, and register itself on the component instance.
  • The Start method is called when the component instance starts. Then the component instance is started. A started component instance is either VALID or INVALID. A component instance is valid all if and only if all plugged handler are valid. In the Start, method a handler needs to start its management (service publication, listener registration...)
  • The Stop method is called when the component instance stops. In the Stop, method a handler needs to release all references on services ...

...

The handler namespace is "org.apache.felix.ipojo.log.handler.LogHandler". It is the handler implementation class too. A developer who wants to use the handler will configure its component type with the following metadata:

Handler implementation

The handler needs to override following methods:

  • Configure : to parse the metadata and get the logging level
  • Start and Stop : to track Log Service
  • stateChanged : to log the message
  • isValid : to be invalid when the Log Service is not available

Log Handler class

...

Code Block
xml
xml

<iPOJO xmlns:log= org.apache.felix.ipojo.log.handler.

...

The handler needs the Log Service. So it will implement the "org.osgi.framework.ServiceListener" interface too.

The class has several other fields:

  • The bundle context (context)
  • The instance manager (manage)
  • The service reference of the actual used Log Service (ref)
  • The used log service (log)
  • The level of the log (level)

Note: Handler code is OSGiâ„¢ standard code. A handler cannot be a POJO.

Configure Method

This method begins by parsing the component type metadata. The handler needs a log element from its namespace. According to the result, the configure method can return immediately or parse the level attribute (to get the logging level). Then, the handler stores some value inside field as the instance manager and the bundle context (note how your handler can access to the bundle context). To finish, the handler must register itself to the instance manager to become a part of the instance container.

The start and stop methods

The start method needs to look for a Log Service, and register a service listener to track it. If a log service is available, it logs a message.

The stop method logs a message if the Log Service is available. Then it releases the used Log Service.

Note: do not forget to unget all used services and to release all service objects.

The isValid and stateChanged methods

The isValid method returns the handler validity. In our case, the handler is valid if a log service is available.

The stateChanged method is called by the instance manager to notify that the component instance state changes. The handler needs to log a message (if the log service is available) containing the new state.

Implementation of the Service Listener interface

...

LogHandler>
<component className="...">
<log:Log level="error"/><!- - error, warning or info accepted - ->
</component>
<instance component="..." name="LogHandlerTest-1"/>
</iPOJO>

Handler implementation

The handler needs to override following methods:

  • Configure : to parse the metadata and get the logging level
  • Start and Stop : to track Log Service
  • stateChanged : to log the message
  • isValid : to be invalid when the Log Service is not available

Log Handler class

The handler is implemented inside the "org.apache.felix.ipojo.log.handler.LogHandler" class. This class extends the "org.apache.felix.ipojo.Handler" class. This class has the final static string field "NAMESPACE", with the "org.apache.felix.ipojo.log.handler.LogHandler" value.

The handler needs the Log Service. So it will implement the "org.osgi.framework.ServiceListener" interface too.

The class has several other fields:

  • The bundle context (context)
  • The instance manager (manage)
  • The service reference of the actual used Log Service (ref)
  • The used log service (log)
  • The level of the log (level)

Note: Handler code is OSGiâ„¢ standard code. A handler cannot be a POJO.

Configure Method

This method begins by parsing the component type metadata. The handler needs a log element from its namespace. According to the result, the configure method can return immediately or parse the level attribute (to get the logging level). Then, the handler stores some value inside field as the instance manager and the bundle context (note how your handler can access to the bundle context). To finish, the handler must register itself to the instance manager to become a part of the instance container.

Code Block
java
java
titleLogHandler.java:ConfigureMethod

public void configure(InstanceManager im, Element metadata, Dictionary config) {
 // First parse the metadata to check if the log handler level
		
 // Get all Namespace:log element from the metadata
 Element[] log_elements = metadata.getElements("log", NAMESPACE);
		
 // if no element found, return 
 if(log_elements.length == 0) { return; } 
 else {
	// If an element match, parse the level attribute of the first element
	if(log_elements[0].containsAttribute("level")) {
		String l = log_elements[0].getAttribute("level");
		if(l.equalsIgnoreCase("info")){level=LogService.LOG_INFO; }
		else if(l.equalsIgnoreCase("error")){level=LogService.LOG_ERROR; }
       	else {level=LogService.LOG_WARNING;}
	}
			
// Register on the instance manager, to be a part of the component                  // instance container
	manager = im;
	context = manager.getContext();  // Store the bundle context
	manager.register(this);
   }
}

The start and stop methods

The start method needs to look for a Log Service, and register a service listener to track it. If a log service is available, it logs a message.

Code Block
java
java
1title:LogHandler.java:Start Method
 
public void start() {
 // When starting, look for an LogService
 ref = context.getServiceReference(LogService.class.getName());
 if(ref != null) { 
   log = (LogService) context.getService(ref);
   // Log a starting message
   log.log(level,"The component instance " + manager.getInstanceName() + " is starting");
 }
// Registered a service listenner
try {
  context.addServiceListener(this,"(OBJECTCLASS="+LogService.class.getName()+")");
} catch (InvalidSyntaxException e) { e.printStackTrace(); }
}

The stop method logs a message if the Log Service is available. Then it releases the used Log Service.

Code Block
java
java
titleLogHandler.java:Stop Method

public void stop() {
 // Log the event, unget the service
 if(log != null) { log.log(level, "The component instance " + 
				manager.getInstanceName() + " is stopping"); }	
 if(ref != null) { log = null; context.ungetService(ref); } 
}

Note: do not forget to unget all used services and to release all service objects.

The isValid and stateChanged methods

The isValid method returns the handler validity. In our case, the handler is valid if a log service is available.

Code Block
java
java
1title:LogHandler.java:isValid Method

public boolean isValid() {
 // The handler is valid <=> a log service is available
 return (ref != null);
}

The stateChanged method is called by the instance manager to notify that the component instance state changes. The handler needs to log a message (if the log service is available) containing the new state.

Code Block
java
java
titleLogHandler.java:stateChanged method

public void stateChanged(int state) {
 // log the state changed events
 if(log != null) {
   if(state == InstanceManager.VALID) { log.log(level, "The component 
instance " + manager.getInstanceName() + " becomes valid"); }
   if(state == InstanceManager.INVALID) { log.log(level, "The component
		instance " + manager.getInstanceName() + " becomes invalid"); }
 }
}
Implementation of the Service Listener interface

To track the availability of the Log Service, the start method has registered the handler as a service listener. So, the handler class needs to implement the Service Listener interface. This interface contains a method called when a service appears, disappears or is modified. The start method has registered a service listener with a filter. So the handler will received only service events matching the filter. (In our case, only service events referring to a Log Service).

Code Block
java
java
titleLogHandler.java:ServiceChanged

public void serviceChanged(ServiceEvent event) {
  // Check if the service event does not infers with the log service
  if(ref == null && event.getType() == ServiceEvent.REGISTERED) {
    ref = event.getServiceReference();
    log = (LogService) context.getService(ref);
    // ask the component manager to check the component instance state
    manager.checkInstanceState();
 }
 if(ref != null && event.getType() == ServiceEvent.UNREGISTERING 
&& ref == event.getServiceReference()) {
  //The log service goes away
  log = null;
  context.ungetService(ref);
  ref = context.getServiceReference(LogService.class.getName());
  if(ref != null) { log = (LogService) context.getService(ref); }
  else { manager.checkInstanceState(); }
 }
}

According to the event type, the method gets or releases a Log Service. If a Log Service appears, the method checks if the handler has already a Log Service. If not, it gets the service object, and asks the component instance to check the instance state because the handler state changes. If a Log Service disappears, the method checks if it used this Log Service. Then, it releases the service and look for another Log Service. If no other Log Service is available, the handler becomes invalid. It asks the instance manager to check the instance state.
Note: another event type exists. The MODIFED event type describes a property change in a service reference. In the example, we don't manage this event type.

...