Reputation: 2089
I have a Liferay system with several portlets. Most of these portlets have redundant JSF related JAR-s in them so I would like to remove the redundancy, and create an OSGI bundle for the commonly used JAR-s.
The idea would be that all of my portlets would use this common bundle as a dependency.
After some reading about I ended up with something similar in my maven pom:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.4</version>
<extensions>true</extensions>
<configuration>
<remoteOBR>true</remoteOBR>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.name}</Bundle-Name>
<Bundle-Vendor>${project.organization.name}</Bundle-Vendor>
<Import-Package>
!sun.reflect,......,*
</Import-Package>
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
</instructions>
</configuration>
</plugin>
And I ended up with the following bundle jar:
My Manifest:
Manifest-Version: 1.0
Bundle-SymbolicName: my-common-bundle
Built-By: pjaloveczki
Bundle-ManifestVersion: 2
Bnd-LastModified: 1537882770915
Embed-Dependency: *;scope=compile|runtime
Import-Package: com.liferay.portal.kernel.exception,com.liferay.portal
.kernel.language,com.liferay.portal.kernel.model,......,org.w3c.dom.styleshe
ets,sun.misc
Tool: Bnd-1.15.0
Bundle-Name: my-common-bundle
Bundle-Version: 1.0.0
Bundle-ClassPath: .,sac-1.3.jar,...all..my..dependecies...,com.liferay.faces.bridge.api-4.1.0.jar
Ignore-Package: net.sf.cglib.proxy,..all..ignored..packages...javax.ejb
Embed-Transitive: true
Created-By: Apache Maven Bundle Plugin
Build-Jdk: 1.8.0_171
Content:
From what I can see, this is exactly what I needed, at least this is how I pictured it.
In my consuming portlet I added the following to my manifest:
Require-Bundle: my-common-bundle;bundle-version="1.0.0"
I figured something like this should work, however I am obviously wrong as when I try to deploy my portlet one of the classes is not being found provided by the common bundle:
java.lang.ClassNotFoundException: org.richfaces.webapp.ResourceServlet cannot be found by MyPortlet
On the other hand if I add the following to my common bundle:
<Export-Package>org.richfaces.webapp</Export-Package>
The class is found, but I am ended up with this:
So essentially I have the class twice once in the JAR and once flattened out, even though it's kind of starting to work.
There are several reason I don't like this approach:
Can anyone help, what it the proper way to use these embedded jars in an OSGI without having to flatten them out?
Thank! Peter
EDIT:
It seems that classes are being deployed fine and are resolved after I've added
<_exportcontents>!org.apache.commons.logging,*</_exportcontents>
however I am getting different types of errors which I am not getting when I put my JARs in my portlets.
Previously I was getting ClassNotFoundErrors and such, now I am getting:
java.lang.NullPointerException
at javax.faces.CurrentThreadToServletContext.getFallbackFactory(CurrentThreadToServletContext.java:79)
at javax.faces.FactoryFinderInstance.getFactory(FactoryFinderInstance.java:551)
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:283)
at javax.faces.webapp.FacesServlet.init(FacesServlet.java:358)
java.lang.NullPointerException
at javax.portlet.faces.GenericFacesPortlet.getBridgeClassName(GenericFacesPortlet.java:193)
at javax.portlet.faces.GenericFacesPortlet.getBridge(GenericFacesPortlet.java:762)
at javax.portlet.faces.GenericFacesPortlet.init(GenericFacesPortlet.java:448)
at com.liferay.portlet.InvokerPortletImpl.init(InvokerPortletImpl.java:297)
It seems to me classes are loaded, but the JAR manifests are not being processed or something similar. Any ideas?
Upvotes: 2
Views: 709
Reputation: 2322
you can use <_exportcontents>
instruction to export the content without duplication, more about it here
I would like to point out that creating fat jars is against the very idea of OSGi, also, this is going to be a nightmare to maintain when your code evolves.
Ideally you would want to have a separate bundle for each dependency. They should be deployed and maintained separately.
Upvotes: 2