Moved to the Liferay Faces - English category.

Péter Jaloveczki, modified 7 Years ago. New Member Posts: 5 Join Date: 6/3/18 Recent Posts

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:

enter image description hereFrom 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:

enter image description here

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:

  1. I would prefer using structured jars because I consider it cleaner
  2. Most of these jars contain configuration files that could overlap if I flatten everything out
  3. 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.

thumbnail
Kyle Joseph Stiemann, modified 7 Years ago. Liferay Master Posts: 760 Join Date: 1/14/13 Recent Posts
Moved to the Liferay Faces - English category.
thumbnail
Kyle Joseph Stiemann, modified 7 Years ago. Liferay Master Posts: 760 Join Date: 1/14/13 Recent Posts

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