Wednesday, January 4, 2012

OSGI commons-logging blues

I read that OSGI plugins is difficult to build because of the isolation built into the plugin ecosystem. But only recently I found out that it is really troublesome, tooks me a lot of time to figure these out:
- Import-Package clause in the plugin could import already loaded classes in the main application onto the plugin. But the precondition is that the main application must already register the already loaded class packages (Java packages, not maven artifactId) onto the plugin ecosystem.
- Imported classes could refer to other classes. Runtime exception could occur unless the other class packages already registered by the main application (ex. in the Felix configuration map) (or exported by other plugin) AND the other class packages is imported in one of the Import-Package clause.
- The Apache commons-logging library is very much not compatible with OSGI

In my case, My plugin has a spring-jdbc library dependency. At first I OSGI-imported spring packages from the main application, only to find out that the main application missed some packages, resulting in Runtime exceptions inside spring instances. Then I forgo the spring import stuffs, making them included dependency instead.
Now I am faced by commons-logging errors.

The final solution is to include spring libraries by transitive dependency but exclude commons-logging, and add SLF4J dependency clauses to replace commons-logging classes :


...
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<!-- Change package and plugin class here -->
<Export-Package>telkom.isc</Export-Package>
<Private-Package>telkom.isc.*</Private-Package>
<Bundle-Activator>telkom.isc.AuditPluginActivator</Bundle-Activator>
<Import-Package>!*,org.joget.report.dao,org.joget.report.model,org.joget.report.service,org.joget.commons.util,org.joget.plugin.base,org.joget.plugin.property.model,org.joget.plugin.property.service,org.joget.directory.model,org.joget.directory.model.service,org.joget.directory.dao,org.joget.workflow.model,org.joget.workflow.model.dao,org.joget.workflow.model.service,org.joget.workflow.util,org.joget.apps.app.dao,org.joget.apps.app.lib,org.joget.apps.app.model,org.joget.apps.app.service,org.joget.apps.datalist.lib,org.joget.apps.datalist.model,org.joget.apps.datalist.service,org.joget.apps.form.lib,org.joget.apps.form.dao,org.joget.apps.form.model,org.joget.apps.form.service,org.joget.apps.list.service,org.joget.apps.userview.lib,org.joget.apps.userview.model,org.joget.apps.userview.service,org.joget.apps.workflow.lib,javax.servlet,javax.servlet.http,org.osgi.framework;version="1.3.0"</Import-Package>
<!-- End change package and plugin class here -->
<Embed-Dependency>scope=compile|runtime;inline=false;artifactId=!commons-logging</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
<Embed-Directory>dependency</Embed-Directory>
<Embed-StripGroup>true</Embed-StripGroup>
<DynamicImport-Package>*</DynamicImport-Package>
</instructions>
</configuration>
</plugin>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>


<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.5.6.SEC02</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>2.5.6.SEC02</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl104-over-slf4j</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>org.joget</groupId>
<artifactId>wflow-core</artifactId>
<version>3.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>10.2.0.2.0</version>
<scope>runtime</scope>
</dependency>
<!-- Change plugin specific dependencies here -->

<!-- End change plugin specific dependencies here -->
</dependencies>