Enabling JSF CDI portlet for Gradle Build

 

At the time of this writing, the Maven archetype for a JSF portlet with CDI enabled generates output that can only be built using Maven in order to enable CDI. This currently works with Liferay Portal 7.3 and not 7.4. With a few tweaks, you can make your JSF portlet use your Gradle build system. Initially, you will use Maven to generate the code and while it does put int a build.gradle, there are missing pieces in order to utilize CDI and all the wonderful services that Liferay provides.

Generate the project in the modules folder of your Liferay Workspace

mvn archetype:generate \
  -DarchetypeGroupId=com.liferay.faces.archetype \
  -DarchetypeArtifactId=com.liferay.faces.archetype.jsf.portlet \
  -DarchetypeVersion=6.1.0 \
  -DgroupId=com.mycompany \
  -DartifactId=com.mycompany.my.jsf.portlet

Modify the pom.xml with the following. There seems to be a bug in the archetype. You will only need this if you decide to run the maven command later to generate the war using the mvn package -P cdi,thin. The objective is to get away from the maven build, yet if you want to compare build output, update the following.

<version>6.1.0-SNAPSHOT</version>

to

<version>6.1.0</version>

Now onto the manual ​​​​​​​updates to enable the Gradle build. Place the following code in the MyBacking.java to inject the service, add a getter for the number of users and add logging.

public int getUserCount () {
        _log.debug("Called get Count");
        return _userLocalService.getUsersCount();
}

@Inject
@Reference
UserLocalService _userLocalService;

private static final Logger _log = LoggerFactory.getLogger(MyBacking.class);

Add the following imports to src/main/java/com/mycompany/backing/MyBacking.java .

import org.osgi.service.cdi.annotations.Reference;
import javax.inject.Inject;
import javax.inject.Named;
import com.liferay.portal.kernel.service.UserLocalService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Under src/main/resources add the sub folder named META-INF/services

cd ./src/main/resources
mkdir -p META-INF/services

Create the files under META-INF/services with the following contents.

  • com.sun.faces.spi.annotationprovider
com.liferay.faces.util.osgi.mojarra.spi.internal.AnnotationProviderOSGiImpl
  • com.sun.faces.util.cdi11.CDIUtil
com.sun.faces.util.cdi11.CDIUtilImpl
  • com.sun.faces.spi.FaceletConfigResourceProvider
com.liferay.faces.util.osgi.mojarra.spi.internal.FaceletConfigResourceProviderOSGiImpl
  • javax.enterprise.inject.spi.Extension
com.liferay.faces.bridge.servlet.BridgeExtension
com.liferay.faces.util.servlet.internal.UtilExtension
com.sun.faces.application.view.ViewScopeExtension 
com.sun.faces.flow.FlowCDIExtension
com.sun.faces.flow.FlowDiscoveryCDIExtension
  • com.sun.faces.spi.FacesConfigResourceProvider
com.liferay.faces.util.osgi.mojarra.spi.internal.FacesConfigResourceProviderOSGiImpl
  • javax.servlet.ServletContainerInitializer
com.sun.faces.config.FacesInitializer
com.liferay.faces.util.osgi.internal.FacesThinWabInitializer
com.liferay.faces.bridge.servlet.BridgeServletContainerInitializer

Under WEB-INF create beans.xml with the following content.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" bean-discovery-mode="all" version="1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd">
</beans>

Add the following to build.gradle.

compileOnly group: "org.osgi", name: "org.osgi.service.cdi", version: "1.0.0"
compileOnly group: "com.liferay.portal", name: "release.portal.api"
compileOnly group: 'org.slf4j', name: 'slf4j-api', version: '1.7.26'

In the file src/main/webapp/WEB-INF/liferay-plugin-package.properties remove the following two lines

${osgi.dynamic.import.package}
${osgi.import.package}

with the following. Note, if it doesn’t work, leave it out.

DynamicImport-Package: \
    com.liferay.faces.bridge.*,\
    com.liferay.faces.portlet.*,\
    com.liferay.faces.util.*,\
    com.sun.faces.*,\
    javax.faces.*,\
    javax.portlet.faces.*
Import-Package: \
    com.liferay.faces.bridge.ext,\
    com.liferay.faces.bridge.impl,\
    com.sun.faces,\
    javax.annotation,\
    javax.faces,\
    javax.portlet.faces,\
    !com.ibm.uvm.tools,\
    net.fortuna.ical4j.*;resolution:=optional,\
    org.apache.axis.tools.ant.*;resolution:=optional,\
    org.apache.poi.*;resolution:=optional,\
    com.swabunga.spell.*;resolution:=optional,\ 
    *

Update the view.xhmtl, so that it references the injected service.

Below this line

<li><em><h:outputText value="#{product.LIFERAY_FACES_UTIL}" /></em></li>

Add a line that references the bean and the userCount attribute in the myBacking bean.

<li><em>This many users registered: <h:outputText value="#{myBacking.userCount}" /></em></li>

You should now be able to execute the following gradle commands on your jsf portlet using gradle and verify that it indeed is using CDI. Look a count of users in the system to verify.

gradlew build
gradlew clean
gradlew deploy

​​​​​​​