Wednesday Aug 18, 2010

Liferay, Glassfish, Hot Deploy

Today I played around with the hotdeplyoment of a portlet into my Liferay server 5.3  which runs on top of Glassfish 2.1.

There are different documentations about this topic. But I run into the problem that my portlet (developed with Eclipse and Maven) was deployed but also immediately undeployed. The deployment process allways ends with a message like:

[#|2010-08-17T13:35:54.446+0200|INFO|sun-appserver9.1|javax.enterprise.system.tools.deployment|_ThreadID=17;_ThreadName=Timer-16;|
[AutoDeploy] Successfully autoundeployed : /opt/glassfish_v2ur2/domains/lportal/autodeploy/imixs-workflow-portlet-sample-0.0.4-SNAPSHOT.war.|#]

I did not know why, but the solution for me was to change the Deploy Directory configured in the liferay server from the Glassfish Autodeploy folder to a directory outside my glassfish/liferay server.

You can change the settings in the Plugin-Installer Portlet from liferay. I did not use the property file 'portal-ext.properties'!

 

After I changed the  "Deploy Directory" and leave the "Destination Directory" blank, hot deployment works for me.

Ok I forget to explain how my portlet goes into my local autodeploy folder ;-)

I am developing my portlets with maven. So in my pom.xml I added the following maven-antrun-plugin which copies the portlet war into my autodeploy folder:

......  
           <plugin>
                <artifactId>maven-antrun-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>pre-integration-test</phase>
                        <configuration>
                            <tasks>
                              
                                <echo message="About to copy plugin to autodeploydirectory..." />
                                <echo> Plugin:
                                    ${project.build.directory}/${project.build.finalName}.war
                                    autodeploy directory: /home/rsoika/liferay_autodeploy </echo>
                                <copy
                                    file="${project.build.directory}/${project.build.finalName}.war"
                                    todir="/home/rsoika/liferay_autodeploy" />
                                <echo message="Copied to portletdeploy directory." />
                            </tasks>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
......

Sunday Aug 01, 2010

Liferay, JSF and Glasssfish

Developing a JSF portlet in Liferay 6.0.4 running on Glassfish 3 is not as easy as it sounds like. I investigated several days (and nights) to found a working solution. I think the reason why it takes so much time for me was the fact that there are to many examples spread over the last two years. And as more you mix them up as more problems occur.   

Running Liferay on top of Glassfish 3 is a good choice as the Glassfish application server supports a powerful platform for EJB and Web development. For the portlet development there are different APIs and specifications which need to be separated with care.

After my personal journey through the portlet/jsf world I come to the conclusion that the best combination of all portlet technologies is the Portlet API 2.0 (JSR 286) and JSF 2.0 (JSR 314). To fit them together you need a JSF-Portlet Bridge.

The best working solution for now seems to be the portletfaces-bridge from portletfaces.org. This bridge is not yet final but it works well with Liferay and Glassfish. ?The portletfaces bridge supports development of JSF 2.0 apps that run inside a Portlet 2.0 compliant portlet container, such as the one provided by Liferay Portal. In addition, the bridge facilitates the deployment of ICEfaces 2.0 applications.

The two artifacts "portletfaces-bridge-api" and portletfaces-bridge-impl"are not available through an official maven repository.So you need to add the Maven repository 'http://repo.portletfaces.org/mvn/maven2/' to your maven settings.xml file. Then you can use them in your projects using maven2.

The current alpha releases are:

  • portletfaces-bridge-api-2.0.0-ALPHA4.jar
  • portletfaces-bridge-impl-2.0.0-ALPHA4.jar

You can checkout an example portlet form the Imixs Workflow Portlet Project at the following location:

https://imixs-workflow.dev.java.net/svn/imixs-workflow/imixs-workflow-portlet-sample/tags/0.0.3

Note: To get access you simply need an account on dev.java.net.

I will post the interesting parts of the example here:

web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">

<description>Imixs RichFacesPortlet</description>
<context-param>
<param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>
<!--
Although the FacesServlet will not be invoked by any portlet requests,
it is required to initialize JSF.
-->
<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>


<security-constraint>
<web-resource-collection>
<web-resource-name>Page Sources</web-resource-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
<url-pattern>*.xhtml</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>nobody</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>nobody</role-name>
</security-role>
</web-app>

portlet.xml

 <?xml version="1.0"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd">
    <portlet>
        <portlet-name>1</portlet-name>
        <display-name>Imixs Portlet Sample RichFaces</display-name>
        <portlet-class>org.portletfaces.bridge.GenericFacesPortlet</portlet-class>
        <init-param>
            <name>javax.portlet.faces.defaultViewId.view</name>
            <value>/pages/echo.xhtml</value>
        </init-param>
        <supports>
            <mime-type>text/html</mime-type>
            <portlet-mode>VIEW</portlet-mode>
        </supports>           
        <portlet-info>
            <title>ImixsRichFacesEchoPortlet</title>
            <short-title>ImixsRichFacesEchoPortlet_Short</short-title>
            <keywords>Sample</keywords>
        </portlet-info>
          <security-role-ref>
            <role-name>administrator</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>guest</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>power-user</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>user</role-name>
        </security-role-ref>       
</portlet>
</portlet-app>


 liferay-plugin-package.properties

 

name=ImixsPortletSample
module-group-id=liferay
module-incremental-version=1
tags=sample
short-description=This plugin leverages the Sun OpenPortal JSF Portlet Bridge and shows how to use the JSF 1.2 Sun RI and the Facelets view-handler within Liferay.
change-log=
page-url=http://www.liferay.com
author=Liferay, Inc.
licenses=MIT

portal-dependency-jars=

 

faces-config.xml

 <?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">
 
   <application>
 
   </application>
   
   <managed-bean>
      <description>Echo Bean</description>
      <managed-bean-name>echo</managed-bean-name>
      <managed-bean-class>com.imixs.portlet.test.EchoBean</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
        <managed-property>
            <property-name>text</property-name>
            <value>Hello Liferay</value>
        </managed-property>
   </managed-bean>

    
</faces-config>