Adding third party jars to Cortex API
Adding third party jars to Cortex API
This section describes how to add third party jars as OSGi dependencies to Cortex.
Determining if a Bundle is OSGi Compliant
Before adding a bundle to Cortex, you must first determine whether it is OSGi compliant or requires work to become so.
There are two ways to determine if a bundle is OSGi compliant. Ideally, a bundle's MANIFEST.MF provides the information required, but if it does not, loading the bundle and building the Cortex webapp can provide information on a bundle's compliance.
Determining Compliance via a Bundle's MANIFEST.MF file
The easiest way to determine if a bundle is OSGi compliant is by inspecting its META-INF/MANIFEST.MF file. Non-OSGi compliant jars don't have bundle key/value tags inside the manifest, while OSGi compliant jars do.
Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: Apache Maven Built-By: hardy Build-Jdk: 1.5.0_20
Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: Apache Maven Bundle Plugin Built-By: hen Build-Jdk: 1.5.0_22 Implementation-Build: UNKNOWN_BRANCH@r??????; 2011-11-09 22:58:07-0800 Implementation-Title: Commons Lang Implementation-Vendor: The Apache Software Foundation Implementation-Vendor-Id: org.apache Implementation-Version: 3.1 Specification-Title: Commons Lang Specification-Vendor: The Apache Software Foundation Specification-Version: 3.1 X-Compile-Source-JDK: 1.5 X-Compile-Target-JDK: 1.5 Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Include-Resource: templates/release-notes.vm=src/main/resources/templa tes/release-notes.vm,META-INF/LICENSE.txt=LICENSE.txt,META-INF/NOTICE .txt=NOTICE.txt Bnd-LastModified: 1320908300777 Export-Package: org.apache.commons.lang3.event;version="3.1",org.apach e.commons.lang3.mutable;version="3.1",org.apache.commons.lang3.tuple; version="3.1",org.apache.commons.lang3.time;version="3.1",org.apache. commons.lang3.concurrent;version="3.1",org.apache.commons.lang3.text. translate;version="3.1",org.apache.commons.lang3.text;version="3.1",o rg.apache.commons.lang3.math;version="3.1",org.apache.commons.lang3;v ersion="3.1",org.apache.commons.lang3.exception;version="3.1",org.apa che.commons.lang3.reflect;version="3.1",org.apache.commons.lang3.buil der;version="3.1" Bundle-Version: 3.1.0 Bundle-Name: Commons Lang Bundle-Description: Commons Lang, a package of Java utility classes fo r the classes that are in java.lang's hierarchy, or are considered t o be so standard as to justify existence in java.lang. Private-Package: templates Bundle-DocURL: http://commons.apache.org/lang/ Bundle-Vendor: The Apache Software Foundation Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.apache.commons.lang3 Tool: Bnd-1.15.0
Determining Compliance via Console Output
Adding a non-OSGi compliant jar to Cortex causes a number of errors and exceptions at runtime, and prevents the webapp from starting up. Errors may range from BundleExceptions to error messaging reading "could not start bundle...", "unresolved requirement..." or more. An example of a runtime error due to a non-OSGi compliant jar is below:
org.osgi.framework.BundleException: Unable to resolve com.elasticpath.rest.integration.epcommerce.ep-resource-orders-epcommerce [181](R 181.0): missing requirement [com.elasticpath.rest.integration.epcommerce.ep-resource-orders-epcommerce [181](R 181.0)] osgi.wiring.package; (osgi.wiring.package=com.does.not.exist) Unresolved requirements: [[com.elasticpath.rest.integration.epcommerce.ep-resource-orders-epcommerce [181](R 181.0)] osgi.wiring.package; (osgi.wiring.package=com.does.not.exist)] at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:4114) ~[org.apache.felix.framework-5.2.0.jar:na] at org.apache.felix.framework.Felix.startBundle(Felix.java:2111) ~[org.apache.felix.framework-5.2.0.jar:na] at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:977) ~[org.apache.felix.framework-5.2.0.jar:na] at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:964) ~[org.apache.felix.framework-5.2.0.jar:na] at org.apache.felix.webconsole.internal.core.BundlesServlet.doPost(BundlesServlet.java:365) ~[na:na] at javax.servlet.http.HttpServlet.service(HttpServlet.java:650) [tomcat-embed-core-7.0.65.jar:7.0.65] at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.felix.webconsole.internal.servlet.OsgiManager.service(OsgiManager.java:567) [org.apache.felix.webconsole-4.2.12.jar:na] at org.apache.felix.webconsole.internal.servlet.OsgiManager$3.run(OsgiManager.java:465) [org.apache.felix.webconsole-4.2.12.jar:na] at java.security.AccessController.doPrivileged(Native Method) [na:1.8.0_131] at org.apache.felix.webconsole.internal.servlet.OsgiManager.service(OsgiManager.java:461) [org.apache.felix.webconsole-4.2.12.jar:na] at org.apache.felix.http.base.internal.handler.ServletHandler.doHandle(ServletHandler.java:339) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.handler.ServletHandler.handle(ServletHandler.java:300) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.ServletPipeline.handle(ServletPipeline.java:93) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:50) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:31) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:84) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:46) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:31) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at com.elasticpath.rest.relos.rs.authentication.springoauth2.filter.OAuth2TokenAuthenticationFilter.doFilter(OAuth2TokenAuthenticationFilter.java:81) [ep-rs-authentication-spring-oauth2-0-SNAPSHOT.jar:na] at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:108) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:80) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:46) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:31) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at com.elasticpath.rest.relos.rs.authentication.web.filter.HeadersRemoverFilter.doFilter(HeadersRemoverFilter.java:107) [ep-rs-authentication-resource-0-SNAPSHOT.jar:na] at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:108) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:80) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:46) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:31) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:84) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:46) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:31) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at com.elasticpath.rest.relos.rs.filter.CharsetEncodingFilter.doFilter(CharsetEncodingFilter.java:43) [ep-rs-jersey-integration-0-SNAPSHOT.jar:na] at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:108) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:80) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:46) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:31) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:84) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:46) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:31) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at com.elasticpath.rest.relos.rs.filter.ExceptionTranslatingFilter.doFilter(ExceptionTranslatingFilter.java:45) [ep-rs-jersey-integration-0-SNAPSHOT.jar:na] at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:108) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:80) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:46) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:31) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.FilterPipeline.dispatch(FilterPipeline.java:76) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.dispatch.Dispatcher.dispatch(Dispatcher.java:49) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at org.apache.felix.http.base.internal.DispatcherServlet.service(DispatcherServlet.java:67) [org.apache.felix.http.bridge-2.3.2.jar:2.3.2] at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.felix.http.proxy.ProxyServlet.service(ProxyServlet.java:60) [org.apache.felix.http.proxy-2.3.2.jar:2.3.2] at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625) [tomcat-embed-core-7.0.65.jar:7.0.65] at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318) [tomcat-embed-core-7.0.65.jar:7.0.65] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-7.0.65.jar:7.0.65] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
To identify specific OSGi issues, use the Apache Felix console to examine a project's bundles. For more information on how to access Apache Felix and use it, see Apache Felix Web Console. In particular, a bundle's status as listed in the Felix web console can offer insight: bundles with an Active state have started correctly, and bundles non-Active states may have had issues. Manually re-deploying specific non-Active bundles produces more console output which can help identify specifically why a bundle may have issues starting up.
Adding OSGi Compliant Jars
If the jar is OSGi compliant, add it to commerce-extensions/ext-cortex-webapp's pom.xml file. During the Webapp's start up, this third party jar is included in Cortex and run as an OSGi bundle.
- With a text editor, open commerce-extensions/ext-cortex-webapp's pom.xml file.
- Add the jar as a dependency using the following
declaration:
<dependencies> ... <dependency> <groupId>com.third.party.group</groupId> <artifactId>third-party-jar</artifactId> <version>1.0.0</version> </dependency> ... </dependencies>
- Add the jar as an artifact item using the following declaration:
<plugin> <groupId>org.apache.maven.plugins</groupId> ... <artifactItems> ... <artifactItem> <groupId>com.third.party.group</groupId> <artifactId>third-party-jar</artifactId> </artifactItem> ... </artifactItems> ... </plugin>
- Rebuild commerce-extensions/ext-cortex-webapp using mvn clean install, and run the Cortex Webapp.
Adding non-OSGi Compliant Jars
Occasionally you will have to add non-OSGi compliant jars to Cortex to support additional functionality. This section details strategies for using non-OSGi compliant bundles in an OSGi environment.
Finding an OSGi Compliant Version of the Jar
In general, this is the preferred method for handing non-OSGi compliant jars, and should be used whenever possible.
Find an OSGi compliant version of the third party jar. There are several sources to finding it; two good sources are listed below.
- http://ebr.springsource.com/repository/app/ - a repository of OSGi compliant jars used for building Spring applications
- http://mvnrepository.com - the central maven repository
Wrap the jar using bndtools
If there is no OSGi compliant version of the jar you require, you can create an OSGi compliant jar using bndtools wrap command.
You can download bndtools here:
BND's wrap command takes an existing jar, guesses the right headers for the jar's manifest, and creates a new OSGi bundle jar.
To wrap an existing jar, run the following from the command line:
bnd wrap osgi.jar *.jar
Use OSGi Framework Properties
By using Cortex's OSGi framework properties, you can set OSGi to export packages of your non-OSGi compliant jars and include them in your Cortex API framework. In general, this method should only be used if the above methods did not work.
- org.osgi.framework.bootdelegation - allows you to specify, at a global framework level, a list of packages to implicitly make available to all bundles in the framework. There is no need to declare the classes in the Import-Package headers of the bundles using them.
- org.osgi.framework.system.packages.extra - allows you to add to the list of packages exported by the System Bundle (bundle id 0). Once exported, the packages are then available to the other bundles in the framework, but only if they are explicitly imported in the bundle's Import-Package headers.
- With a text editor, open ext-cortex-webapp/src/main/resources/spring/applicationContext.xml
- Add the third party jar to the org.osgi.framework.bootdelegation list:ext-cortex-webapp applicationContext.xml
... <bean name="osgiFrameworkProperties" class="java.util.HashMap"> <constructor-arg> <map> ... <entry key="org.osgi.framework.bootdelegation" value="org.w3c.dom.ranges, org.w3c.dom.traversal, org.w3c.dom.bootstrap, org.w3c.dom.events, org.w3c.dom.ls, javax.xml.parsers, sun.reflect, org.apache.xerces.jaxp, javax.inject, javax.net.ssl, javax.validation, javax.validation.bootstrap, javax.validation.spi, javax.validation.metadata, javax.management, oracle.sql"/commerce-legacy/> </map> </constructor-arg> ... </bean>
- Add the third party jar to the org.osgi.framework.system.packages.extra list:ext-cortex-webapp applicationContext.xml
... <bean name="osgiFrameworkProperties" class="java.util.HashMap"> <constructor-arg> <map> ... <entry key="org.osgi.framework.system.packages.extra" value=" javax.inject;version=1.0, javax.jms;version=1.1.1, javax.validation;version=1.1.0, javax.validation.bootstrap, javax.validation.constraints, javax.validation.groups, javax.validation.metadata;version=1.1.0, javax.validation.spi, javax.servlet;javax.servlet.descriptor;javax.servlet.http;version=3.0, javax.servlet.annotation;version=3.0, sun.misc, org.w3c.dom.traversal, org.w3c.dom.ranges, org.slf4j;org.slf4j.spi;org.slf4j.helpers;version=1.7.12 "/commerce-legacy/> ... </bean>
- Add the jar artifact as a dependency in ext-cortex-webapp's pom.xml file:
<dependencies> ... <dependency> <groupId>com.third.party.group</groupId> <artifactId>third-party-jar</artifactId> <version>1.0.0</version> </dependency> ... </dependencies>
- Rebuild ext-cortex-webapp using mvn clean install, and run theCortex Webapp.
If your bundle has an Import-Package declaration for a jar, simply declaring the bundle in org.osgi.framework.bootdelegation will not be enough since it only makes the package available in the class loader. You must also declare the package in the org.osgi.framework.system.packages.extra for the bundle to be differentiated from the system bundle.
The general rule is use org.osgi.framework.bootdelegation when you don't have control over the manifest of the problematic bundle and you don't mind exposing the package to every other bundle. Use org.osgi.framework.system.packages.extra when a bundle imports a package and you expect the system bundle (not another bundle) to provide it.