Error CSS Stylesheet macro - Import URL 'http://felix.apache.org/ipojo/site/superfish.css' is not whitelisted. If you want to include this content, contact your Confluence administrator to request whitelisting this URL.
Error CSS Stylesheet macro - Import URL 'http://felix.apache.org/ipojo/site/style.css' is not whitelisted. If you want to include this content, contact your Confluence administrator to request whitelisting this URL.

Apache Felix iPOJO FAQ

Injecting the bundle context in a POJO

It is sometimes useful to inject the bundle context in your POJO. Then, your POJO is able to deal with the OSGi environment as regular OSGi applications. It is possible to a POJO to get its BundleContext. A POJO can receive its bundle context as an argument of its constructor. The next code snippet shows an example:

public class ASimplePOJO{
	private BundleContext context;
	public ASimplePOJO(BundleContext bc) {
		context = bc;
		// do something...
	}}

As you see on the previous snippet, the bundle context is injected in the POJO. Then the POJO can use it as a 'normal' bundle context. The POJO code can:

  • load classes
  • register / unregister services
  • discover, track and use services

However, all these interactions are no more managed by the iPOJO container. So, be careful to manage the dynamism, synchronization, listeners...

Accessing services inside inner and anonymous classes

An inner class is a class defined inside another class. This mechanism is useful in order to avoid creating a bunch of small files. So, it is common when creating threads, Swing listeners ... Generally speaking, inner classes are regular classes treated as separate classes. However this is an oversimplification. Some of the information about an inner class is not in its class file. See section 4.7.5 for further details:
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html

An inner class can access fields of its outer class. Since the iPOJO 1.0.0 version, fields managed by iPOJO, such as a service dependencies and properties, are also available from the inner class. Indeed, iPOJO manipulation also manipulates inner and nested classes, and accesses to outer class fields are correctly managed.

Using a different version of the manipulator during the manipulation

You can configure the version of the manipulator that you want to use when you're using the maven-ipojo-plugin or the iPOJO ant task. This allows to benefit latest improvements.

For Maven, Just declare a dependency on the manipulator that you want to use in the maven-ipojo-plugin plugin section:

Maven
<plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-ipojo-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>ipojo-bundle</goal>
            </goals>
          </execution>
        </executions>
        <dependencies>
        	<dependency>
        		<groupId>org.apache.felix</groupId>
        		<artifactId>org.apache.felix.ipojo.manipulator</artifactId>
        		<version>1.6.2</version>
        	</dependency>
        </dependencies>
      </plugin>

For Ant, just configure the classpath of the iPOJO ant task with the Manipulator that you want to use:

Ant
<taskdef name="ipojo"
        classname="org.apache.felix.ipojo.task.IPojoTask"
                classpath="../ipojo/manipulator/org.apache.felix.ipojo.manipulator-1.7.0-SNAPSHOT.jar; lib/org.apache.felix.ipojo.ant-1.7.0-SNAPSHOT.jar;" />
 />

Callbacks order.

A lot of handlers define callbacks to notify the implementation class. The 'core' callbacks are called in the following order:

@Component
@Provides
public class CallbacksOrder implements MyService {

	public CallbacksOrder() {
		System.out.println("1 Constructor");
	}

	@Bind
	public void bind(LogService log) {
		System.out.println("2 Bind " + log);
	}

	@Property(name="prop")
	public void setProp(String v) {
		System.out.println("3 Set prop " + v);
	}


	@Validate
	public void validate() {
		System.out.println("4 Validate");
	}

	@PostRegistration
	public void registered(ServiceReference ref) {
		System.out.println("5 Registered");
	}

	// --- On Service Departure ---

	@Unbind
	public void unbind(LogService log) {
		System.out.println("6 Unbind " + log);
	}

	// Remaining of the flow


	@PostUnregistration
	public void unregistered(ServiceReference ref) {
		System.out.println("7 Unregistered");
	}

	@Invalidate
	public void invalidate() {
		System.out.println("8 Invalidate");
	}

        // --- End of the callback order

	public void doNothing() {
		// Do nothing...
	}

}

Disabling proxies in iPOJO 1.6+

iPOJO 1.6.0 has generalized the proxy usage. However this mechanism can be disabled.

To disable the proxies on the entire framework, just set the property ipojo.proxy to disabled (this set the default 'proxy' value). This property is either a system property (-Dipojo.proxy=disabled in the command line) or a framework property (given to the framework during its initialization).

You can also disable proxies for specific dependencies by using the proxy attribute:

@Requires(proxy=false)
private LogService log

or

<requires field="log" proxy="false"/>

The default value of the proxy attribute is the value of the ipojo.proxy property.

Use dynamic proxies instead of smart proxies

Smart proxies are generated on the fly using bytecode generation. However this mechanism may not be always supported by the VM (like Dalvik (Android)). To disabled smart proxies (used by default) and use dynamic proxy instead, set the property ipojo.proxy.type to dynamic-proxy. This property is either a system property or a framework property.

Can I use iPOJO with other OSGi implementations?

iPOJO relies on the OSGi R4.1 specification, so works on any compliant implementation. Moreover, iPOJO is weekly tested on Apache Felix, Eclipse Equinox and Knopflerfish..
For further information, refer to the supported OSGi implementations page and on this blog post.

Detecting optional service unavailability

Sometimes it is useful to check if an optional service dependency is fulfilled or not. In order to propose a pretty simple development model, iPOJO injects proxies by default which avoid such check (Because proxies hide such details). By disabling proxies, you can easily check to unavailability.

  • First, disable the proxy injection:
    @Requires(proxy=false)
    private LogService log;
    
  • The injected object will be a direct reference. By default, iPOJO injects a Nullable object, on which you can call service method without checking for null. To detect Nullable objects, just use instanceof
    @Requires(proxy=false)
    private LogService log;
    
    public void doSomething() {
        if (log instanceof Nullable) {
            // Service unavailable
        } else {
           // Service available
        }
    }
    
  • If you prefer injecting null instead of a Nullable, just disable Nullable injection too. However, be care to check for null before each invocation.
    @Requires(proxy=false, nullable=false)
    private LogService log;
    
    public void doSomething() {
        if (log == null) {
            // Service unavailable
        } else {
           // Service available
        }
    }
    

Setting the iPOJO log level

By default, iPOJO logs only warning and error messages. There are two different methods to configure the log level. First, you can set the global log level by setting the ipojo.log.level system property. This replaces the default log level (warning). All iPOJO instances will be impacted. However, each bundle containing component types can specify a different log level. To set this level, add the ipojo-log-level header in your manifest. The possible values for these two properties are:

  • info
  • debug
  • warning (default)
  • error

Installing iPOJO in Service Mix Kernel

You can use iPOJO in Service Mix Kernel. To deploy and start it, just execute the following command line in the ServiceMix Kernel Shell.

osgi install -s mvn:org.apache.felix/org.apache.felix.ipojo/1.2.0

The iPOJO bundle is downloaded from the central maven repository.

iPOJO and File Install

Thanks to File install you can create, disposed and reconfigure instances from cfg files. You can also reconfiguring a creatged instance (configured to expose a ManagedService) with cfg files too. More information about this topic is available here.

iPOJO handler start level

iPOJO Handlers have a start level. This is not the OSGi Start Level. This level is used to determine in which order handler are configured, started and stopped. Handlers with a low level are configured and started before handlers with a high level. Moreover they are stopped after handlers with a high level. By default, handlers have no level. It means that they have the maximum level (Integer.MAX).

Here are the levels of core handlers:

  • Service Dependency: 0 (minimum level)
  • Lifecycle Callback: 1
  • Configuration Properties: 1
  • Service Providing: 3
  • Controller Handler: no level (Integer.MAX)
  • Architecture Handler: no level (Integer.MAX)

From these levels, we can see that bind methods will be called before set methods from configuration properties. So, when a POJO objects, callback are called in this order:

  1. bind methods
  2. validate method
  3. setter methods from instance configuration

Changes in the 1.3.0-SNAPSHOT

iPOJO 1.3.0-SNAPSHOT sets the lifecycle callback handler level to 2. So, setter methods from instance properties are called before the validate method.

Why does my bundle import unused packages?

If you check iPOJO bundle imported packages, you will see that some packages where added:

  • org.apache.felix.ipojo;version= 1.2.0
  • org.apache.felix.ipojo.architecture;version= 1.2.0
  • org.osgi.service.cm;version=1.2
  • org.osgi.service.log;version=1.3

The org.apache.felix.ipojo package is the main iPOJO package. Manipulated class use it to get access to injected values. The org.apache.felix.ipojo.architecture package is used to expose Architecture service (allowing instance introspection). This service is exposed with the bundle context from the bundle declaring the component type.
The org.osgi.service.cm package is imported to publish ManagedService and ManagedServiceFactory with the bundle context from the bundle declaring the component type. So, if you look for services exposed by a bundle declaring component types, you will see ManagedServiceFactory services.
Finally, the org.osgi.service.log is imported because iPOJO delegates log to a log service (if available). This service is get from the bundle context from the bundle declaring the component type. So, to get this service, the package of the service interface is imported. Then, according to implementations, log services may get the bundle logging the message.

How does iPOJO compare to Declarative Services or Blueprint?

The following table highlights some of the features of each system, it does not attempt to highlight every feature of each.

Dependency injection

Declarative Services

Blueprint

iPOJO

Callback injection

Yes

Yes (public method only)

Yes

Constructor injection

No

Yes

Yes

Field injection

No

No

Yes

Setter injection

Yes

Yes

Yes

Proxy injection

No

Yes

Yes

List injection

No

Yes

Yes

Nullable injection

No

No

Yes

Lifecycle

Declarative Services

Blueprint

iPOJO

Callbacks (activate/deactivate)

Yes

Yes

Yes

Factory pattern

Yes

Yes

Yes

Lazy initialization

Yes

Yes

Yes

Damping

No

Yes

Yes

Field synchronization

No

No

Yes

Component lifecycle control

Yes

Partial

Yes

Service lifecycle control

No

No

Yes

Configuration

Declarative Services

Blueprint

iPOJO

Property configuration

No

Yes

Yes

Field configuration

No

No

Yes

Configuration Admin

Yes

No

Yes

Services

Declarative Services

Blueprint

iPOJO

Custom attribute type

No

Yes

Yes

Lazy initialization

Yes

Yes

Yes

Composite services

No

No

Yes

Component description

Declarative Services

Blueprint

iPOJO

XML

Yes

Yes

Yes

Java annotations

No

No

Yes

API

No

No

Yes

Nonfunctional

Declarative Services

Blueprint

iPOJO

Multiple providers

Yes

Yes

No



  • No labels