Monday, August 1, 2016

Using External JAR Files in WSO2 Servers

When using WSO2 Servers, we may need to use some third party Java libraries for getting our use cases to work.

One simple example is using a MySQL database as a userstore in a WSO2 server. In that case, we need to copy MySQL JDBC Driver jar file to WSO2 server because by default WSO2 products are not shipping any JDBC connectors.

Another example would be writing our own custom components using external dependencies. We may write a notification sender module where we use apache.commons.email library for sending out emails.

In any of these use cases, what we have to do is simply take the particular JAR file that WSO2 server would need to be dependent on and copy it to the relevant location in the server. When copying the JAR file, you need to consider two factors.

The JAR file is OSGI compatible

WSO2 servers use OSGI Java framework for deploying modular software programs. (A WSO2 server is a collection of OSGI compatible bundles located in SERVER_HOME/repository/components/plugins directory that are picked and registered when the server starts up) Therefore in order to pick a JAR file by the server for running, the JAR file should be OSGI compatible.

How to check if the JAR file is OSGI compatible ? You can simply open the JAR file from an archive manager (or extract the JAR file) and open META-INF/MANIFEST.MF file. If the JAR file is OSGI compatible, you can find Bundle-SymbolicName property in the manifest file [1]. If it is not there, then the JAR file is not OSGI compatible.

Such OSGI compatible JAR files, you have to copy to WSO2_SERVER_HOME/repository/components/dropins directory.


The JAR file is not OSGI compatible

When you open the JAR file and view META-INF/MANIFEST.MF file, if you cannot find Bundle-SymbolicName property, then the JAR file is not OSGI compatible.

Such non OSGI JAR files, you have to copy to WSO2_SERVER_HOME/repository/components/lib directory.  

When the WSO2 server starts up, it will read this directory and identify the newly added non OSGI JAR files. Then the server will automatically modify the META-INF/MANIFEST.MF file of the JAR file and make the JAR file OSGI compatible (adding some meta data). This OSGI compatible JAR file would then be automatically copied to WSO2_SERVER_HOME/repository/components/dropins directory to be picked up by the server since it is now compatible with OSGI runtime and can work with the server.

Not sure the JAR file is OSGI or non OSGI ?

If you are still not sure if the JAR file that you need to copy to the WSO2 server is OSGI compatible or not, just copy it to WSO2_SERVER_HOME/repository/components/lib directory. When the server starts up, if the JAR file is not OSGI compatible, the server will modify the metadata of the JAR file and get the modified JAR file copied to the dropins directory so that it would be picked up.

What is recommended ?

If the JAR file is not written by you, but an external one, it is better that you copy it to WSO2_SERVER_HOME/repository/components/lib directory and let WSO2 server modify the metadata of MANIFEST.MF file to make it compatible with OSGI run time.

The reason is, I downloaded MySQL JDBC Driver and checked the MANIFEST.MF file where I found out that the JAR file is already OSGI compatible (by looking at Bundle-SymbolicName metadata). However when I copied it to the dropins directory of WSO2 server, it was not correctly picked up. When I copied it to the repository/components/lib directory, server automatically wrapped the JAR file and modified the metadata of the MANIFEST and it was then picked up by the server correctly.

MySQL JDBC Driver MANIFEST.MF (Original)
MANIFEST.MF modified by WSO2 server
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.2
Created-By: 1.5.0_22-b03 (Sun Microsystems Inc.)
Built-By: pb2user
Specification-Title: JDBC
Specification-Version: 4.2
Specification-Vendor: Oracle Corporation
Implementation-Title: MySQL Connector Java
Implementation-Version: 5.1.39
Implementation-Vendor-Id: com.mysql
Implementation-Vendor: Oracle
Bundle-Vendor: Oracle Corporation
Bundle-Classpath: .
Bundle-Version: 5.1.39
Bundle-Name: Oracle Corporation's JDBC Driver for MySQL
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.mysql.jdbc
Export-Package: com.mysql.jdbc;version="5.1.39";uses:="com.mysql.jdbc.
log,javax.naming,javax.net.ssl,javax.xml.transform,org.xml.sax",com.m
ysql.jdbc.jdbc2.optional;version="5.1.39";uses:="com.mysql.jdbc,com.m
ysql.jdbc.log,javax.naming,javax.sql,javax.transaction.xa",com.mysql.
jdbc.log;version="5.1.39",com.mysql.jdbc.profiler;version="5.1.39";us
es:="com.mysql.jdbc",com.mysql.jdbc.util;version="5.1.39";uses:="com.
mysql.jdbc.log",com.mysql.jdbc.exceptions;version="5.1.39",com.mysql.
jdbc.exceptions.jdbc4;version="5.1.39";uses:="com.mysql.jdbc",com.mys
ql.jdbc.interceptors;version="5.1.39";uses:="com.mysql.jdbc",com.mysq
l.jdbc.integration.c3p0;version="5.1.39",com.mysql.jdbc.integration.j
boss;version="5.1.39",com.mysql.jdbc.configs;version="5.1.39",org.gjt
.mm.mysql;version="5.1.39",com.mysql.fabric.jdbc;version="5.1.39";use
s:="com.mysql.jdbc"
Import-Package: javax.net,javax.net.ssl;version="[1.0.1, 2.0.0)";resol
ution:=optional,javax.xml.parsers, javax.xml.stream,javax.xml.transfo
rm,javax.xml.transform.dom,javax.xml.transform.sax,javax.xml.transfor
m.stax,javax.xml.transform.stream,org.w3c.dom,org.xml.sax,org.xml.sax
.helpers;resolution:=optional,javax.naming,javax.naming.spi,javax.sql
,javax.transaction.xa;version="[1.0.1, 2.0.0)";resolution:=optional,c
om.mchange.v2.c3p0;version="[0.9.1.2, 1.0.0)";resolution:=optional,or
g.jboss.resource.adapter.jdbc;resolution:=optional,org.jboss.resource
.adapter.jdbc.vendor;resolution:=optional

Manifest-Version: 1.0
Export-Package: com.mysql.fabric,com.mysql.fabric.hibernate,com.mysql.
fabric.jdbc,com.mysql.fabric.proto.xmlrpc,com.mysql.fabric.xmlrpc,com
.mysql.fabric.xmlrpc.base,com.mysql.fabric.xmlrpc.exceptions,com.mysq
l.jdbc,com.mysql.jdbc.authentication,com.mysql.jdbc.exceptions,com.my
sql.jdbc.exceptions.jdbc4,com.mysql.jdbc.integration.c3p0,com.mysql.j
dbc.integration.jboss,com.mysql.jdbc.interceptors,com.mysql.jdbc.jdbc
2.optional,com.mysql.jdbc.jmx,com.mysql.jdbc.log,com.mysql.jdbc.profi
ler,com.mysql.jdbc.util,org.gjt.mm.mysql
DynamicImport-Package: *
Bundle-ClassPath: .,mysql-connector-java-5.1.39-bin.jar
Bundle-Version: 1.0.0
Bundle-Name: mysql_connector_java_5.1.39_bin
Bundle-ManifestVersion: 2
Bundle-SymbolicName: mysql_connector_java_5.1.39_bin


Therefore, if the JAR file is not written by you, it is better to copy to the repository/components/lib directory and let the server make it OSGI supported.
References



Tharindu Edirisinghe
Platform Security Team
WSO2

1 comment:

  1. Thats a nice blog. But i am curious about hot deployment of osgi bundle. Is there any way that the osgi framework will pick up my .jar/.car file from WSO2_SERVER_HOME/repository/components/dropins/ and deploy the bundle automatically???

    ReplyDelete