Ask Questions and Find Answers
Important:
Ask is now read-only. You can review any existing questions and answers, but not add anything new.
But - don't panic! While ask is no more, we've replaced it with discuss - the new Liferay Discussion Forum! Read more here here or just visit the site here:
discuss.liferay.com
Moved to the Liferay Faces - English category.
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:
- I would prefer using structured jars because I consider it cleaner
 - Most of these jars contain configuration files that could overlap if I flatten everything out
 - There must be a way to use embedded jars properly since otherwise this feature would not exist
 
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?
I have to reiterate, that if I cope same jars in the bundle in my portlet everything works fine.
Hi Peter,
 Technically this approach could work, but you’re
  going to run into some difficult issues. We might not be able to help
  with your specific approach, but…we’re actually planning on making the
    Liferay Faces jars into OSGi bundles so they can be deployed to 
    $LIFERAY_HOME/osgi/modules (instead of
  including them in each WAR's 
    WEB-INF/lib folder). If you’re feeling
  adventurous, you could build the branches listed my latest comment in
    FACES-3024
  from source and try it out. Also, even with everything (mostly)
  working, we still had to include the RichFaces jar in the WAR's 
    WEB-INF/lib folder since it is not an OSGi
  bundle. If you decide that you still want to create a common OSGi jar,
  there’s no guarantee that we can support you, but you can take a look
  at FACES-3024 and the linked github branches for information about how
  we dealt with JSF/OSGi incompatibilities.
- Kyle
