cancel
Showing results for 
Search instead for 
Did you mean: 

How-To: Installing Alfresco 2.0 on GlassFish v2

nickmalthus
Champ in-the-making
Champ in-the-making
Alfresco deployment to GlassFish

I noticed that the Alfresco forums and documentation did not mention many references to deploying Alfresco to Sun’s open source application server GlassFish. I wanted to run Alfresco on GlassFish so I spent a considerable amount of time the past couple of days attempting to do so. I wanted to share what I discovered during the process for future reference and to assist with making Alfresco more portable across application servers.

My first attempt at running Alfresco 2.0 on GlassFish v2 B37 with JDK 1.6 involved removing the myfaces implementation and letting Alfresco use the JSF 1.2 implementation included with GlassFish. After all, the JSF 1.2 spec claims to be 1.1 backwards compatible in most cases.

The first issue I encountered was that when I attempted to deploy alfresco to GlassFish I got an OutOfMemory genPerm error. I was able to quickly fix it by running the asadmin command

asadmin create-jvm-options – "-XX\\:MaxPermSize=128m"

I also placed the cryptix-jce-provider.jar in the GlassFish Domain’s lib directory to fix a security issue I encountered.

The Alfresco 2.0 WCM web UI is based on Java Server Faces 1.1. However, it is not completely portable across JSF implementations. There are several dependencies on the MyFaces implementation classes, most notably org.alfresco.web.ui.common.Utils and the call from generateFormSubmit to the myfaces HtmlFormRendererBase.addHiddenCommandParameter(). This utility method generated many of the links in Alfresco and without it working correctly none of the links in the WCM application would function properly (one can’t generate myfaces links that the Sun RI understands). According to the myfaces comments in the HtmlFormRendererBase  code the need for this method was addressed in JSF 1.2 but I did not know enough about JSF 1.2 and how JSF was used by Alfresco to generate the links in order to update it. I also found out that the <h: form acceptCharset referenced in over a hundred Alfresco JSP files was cited as being incorrect by the JSP 2.1 compiler and should have been acceptcharset according to the JSF 1.2 TLD. After discovering other additional dependencies on the myfaces implementation classes, I decided that modifying Alfresco to be JSF implementation agnostic would be too difficult and be too much of a maintenance headache to pursue any further.

My next attempt was to deploy Alfresco to GlassFish and to configure the web app so the bundled myfaces implementation would override the default Sun JSF 1.2 RI implementation. This was no small feat because GlassFish implements JavaEE 5 which is the first EE release that has JSF baked in. Because of this, it is next to impossible to override the bundled JavaEE classes. First, if during application initialization GlassFish sees the Faces Servlet registered in the application’s web.xml it will then initialize it’s own Faces implementation automatically. Fortunately, even though the Faces Servlet is final, myfaces has it’s own Faces Servlet that wraps the JSF Faces Servlet and can be used instead.

<servlet>
      <servlet-name>Faces Servlet</servlet-name>
      <servlet-class>org.apache.myfaces.webapp.MyFacesServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>


Secondly, after some research, I found out I could add an additional Sun deployment descriptor /WEB-INF/sun-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">
<sun-web-app>
  <class-loader delegate="false"/>
</sun-web-app>
To the Alfresco web application. This tells the GlassFish web container to load classes from the web application first and then from the container. However, since javax.faces is now included with JavaEE those classes were protected and the JSF 1.2 API was still being loaded. Editing the <GF_HOME>/lib/processLauncher.xml file and modifying the as9-server configuration to have

<sysproperty key="com.sun.enterprise.overrideablejavaxpackages"
            value="javax.help,javax.portlet,javax.faces"/>

fixed that issue so that the JSF 1.1 API classes were loaded from the myfaces web application. However, the JSP compiler, according to the JSP 2.1 spec, still included the Sun RI taglib classes instead of the myfaces taglib implementation from the web app. Ignoring TLD declarations for the JSF taglib namespace is hard coded in the GlassFish JSP compiler so there is no way around it. To get around this, I extracted the myfaces_core.tld and myfaces_html.tld from the myfaces_impl.jar in the Alfresco WEB-INF/lib directory to the WEB-INF directory. I then created a script to search and replace the following values

http://java.sun.com/jsf/core -> http://myfaces.apache.org/jsf/core
http://java.sun.com/jsf/html-> http://myfaces.apache.org/jsf/html


in all of the jsp and tld files located in the Alfresco war file.

After redeploying, Alfresco WCM was running!!!!! I made it half way through the tutorial without any exceptions in the logs so I am pretty sure it is solid.

To make Alfresco more JavaEE compliant I would suggest the following to the Alfresco developers:

Do a recursive search for “myfaces” in all of the alfresco Java source files. There are not that many actually. See if the dependencies on the myfaces implementation classes can be easily re-implemented in a standard way. MyFaces JSF 1.2 support is still in development but all JSP 2.1 containers must support it to be JavaEE compliant so sooner or later the move the JSF 1.2 will be required to run on JavaEE version of JBoss and Tomcat.

As a side note, the method signature of sun.text.Normalizer has changed in JDK 1.6 and the same functionality is now included in java.text.Normalizer. Please consider modifying the way the Normalizer is included so Alfresco 2.0 WCM can be compiled without modification using JDK 1.6
25 REPLIES 25

amerigo5
Champ in-the-making
Champ in-the-making
Since GlassFish v2 will be out soon, please test the GlassFish v2 (RC).

Thanks.


Actually, this method works has been tested only with Alfresco 2.0 CE. I will try an upgrade on Alfresco 2.1 ASAP.

If you send me the version of glassfish you wanted to used, I can test it.

offtopic
Champ in-the-making
Champ in-the-making
That would be cool, thanks.

rlubke
Champ in-the-making
Champ in-the-making
Yes that's what I thought too. But note that the source code looks like:

140     private class _EntityResolver implements EntityResolver
141     {
142         public InputSource resolveEntity(String publicId, String systemId) throws IOException
143         {
144             if (systemId == null)
145             {
146                 throw new UnsupportedOperationException("systemId must not be null");
147             }
148
149             if (systemId.equals(WebXmlParser.WEB_APP_2_2_SYSTEM_ID) ||
150                 systemId.equals(WebXmlParser.WEB_APP_2_2_J2EE_SYSTEM_ID))
151             {
152                 //Load DTD from servlet.jar
153                 return createClassloaderInputSource(publicId, WebXmlParser.WEB_APP_2_2_RESOURCE);
154             }
155             else if (systemId.equals(WebXmlParser.WEB_APP_2_3_SYSTEM_ID))
156             {
157                 //Load DTD from servlet.jar
158                 return createClassloaderInputSource(publicId, WebXmlParser.WEB_APP_2_3_RESOURCE);
159             }
160             else
161             {
162                 //Load additional entities from web context
163                 return createContextInputSource(publicId, systemId);
164             }

whith the following constants:

54      private static final String WEB_APP_2_2_J2EE_SYSTEM_ID = "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd";
55      private static final String WEB_APP_2_2_SYSTEM_ID = "http://java.sun.com/dtd/web-app_2_2.dtd";
56      private static final String WEB_APP_2_2_RESOURCE  = "javax/servlet/resources/web-app_2_2.dtd";
57 
58      private static final String WEB_APP_2_3_SYSTEM_ID = "http://java.sun.com/dtd/web-app_2_3.dtd";
59      private static final String WEB_APP_2_3_RESOURCE  = "javax/servlet/resources/web-app_2_3.dtd";

So I really do not understand….  But it seems that it is a Glassfish issue.

It seems to work by simply deleting the DOCTYPE declaration (!!??!!), so keep going on…

Are you behind a firewall when you're trying to start the application?  The comments state it's looking
for a DTD in the servlet.jar - that may not necessarily be where it will be in GlassFish.  My guess is if
they can't find the DTD in a jar resource, then they defer to the standard processing where the parser
will try to access http://java.sun.com/dtd/web-app_2_3.dtd.  If it can't access that URL, you will have issues.

So I'm not sure if this is a GlassFish bug.  It sounds more than likely a MyFaces issue.

naramski
Champ in-the-making
Champ in-the-making
Because my website is now down, I publish here the procedure to deploy Alfresco (2.x, x = 0 | 1) to Glassfish v2.

First of all, you have to customize the Alfresco community distribution. The ant script below do the job for me. First, I overwrite the web.xml from Alfresco. This step depends on the Alfresco's version, because web.xml is different in 2.0 and 2.1. After overwriting web.xml, I replace all the taglib standard JSF by MyFaces taglib. This step to make sure Alfresco use MyFaces instead of Glassfish embedded JSF implementation. This step is done by the replace tag in ant script.

For Glassfish, I change the file processLauncher.xml (in <GLASSFISH_HOME>/lib).

   <replace file="${install_prefix}/glassfish/lib/processLauncher.xml" token="javax.help,javax.portlet" value="javax.help,javax.portlet,javax.faces" />

This allow the MyFaces implementation to override the standard embedded JSF.

=================== WEB.XML ==============================

1) I had to replace the DTD declaration by :

<web-app id="WebApp_ID" version="2.5"
   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/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd">

2) The Faces Servlet make explicit use of MyFaces :

  <servlet>
      <servlet-name>Faces Servlet</servlet-name>
      <servlet-class>org.apache.myfaces.webapp.MyFacesServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>

3) I add the taglib resources to the end

   <taglib>
      <taglib-uri>http://myfaces.apache.org/jsf/core</taglib-uri>
      <taglib-location>/WEB-INF/myfaces_core.tld</taglib-location>
   </taglib>
   
   <taglib>
      <taglib-uri>http://myfaces.apache.org/jsf/html</taglib-uri>
      <taglib-location>/WEB-INF/myfaces_html.tld</taglib-location>
   </taglib>


=========== ANT SCRIPT ============

<project default="default">

   <target name="default">
      <mkdir dir="dist" />
      <unzip src="alfresco-community-war-${version}.zip" dest="dist" />
      <mkdir dir="target" />

      <!– On décompresse le WAR dans un répertoire de travail –>
      <unzip src="dist/alfresco.war" dest="target" />
      
      <copy todir="target" overwrite="true">
         <fileset dir="src/main/web">
            <include name="**/*" />
         </fileset>
      </copy>
      
      <replace dir="target" token="http://java.sun.com/jsf/html" value="http://myfaces.apache.org/jsf/html'/>
      <replace dir="target" token="http://java.sun.com/jsf/core" value="http://myfaces.apache.org/jsf/core'/>
      
      <!– Et voila, on repackage –>
      <war destfile="alfresco.war" webxml="target/WEB-INF/web.xml">
         <fileset dir="target">
            <include name="**/*" />
         </fileset>
      </war>

   </target>

</project>

chndu6ue
Champ in-the-making
Champ in-the-making
Deploy Myfaces 1.1 application on Glassfish
I followed the instruction step-by-step given in this forum to deploy my e-commerce application on Glassfish . But it did not work.

Following Steps Works:
1) Add WEB-INF\sun.web.xml with following content


<?xml version="1.0" encoding="UTF-8"?>
<!–
Copyright 2004-2005 Sun Microsystems, Inc.  All rights reserved.
Use is subject to license terms.
–>

<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 Servlet 2.4//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_4-1.dtd">
<sun-web-app>
  <class-loader delegate="false"/>
  <property name="useMyFaces" value="true"/>
</sun-web-app>

2) Remove DOCTYPE Declaration from WEB-INF\web.xml
This will solve the java.sun.com ..ConnectionTimeoutException caused by Myfaces StartupContextListener->WebXml.parse

3) Add version to 2.3 to WEB-INF\web.xml  as follow.
<web-app version="2.3">

Would fix following error
[#|2008-10-05T12:00:42.156+0530|SEVERE|sun-appserver9.1|javax.enterprise.system.container.web|_ThreadID=25;_ThreadName=
ttpSSLWorkerThread-8080-0;_RequestID=8c8dd2a4-a69e-4824-a59d-16c310dca347;|StandardWrapperValve[jsp]: PWC1406: Servlet.
ervice() for servlet jsp threw exception
org.apache.jasper.JasperException: /index.jsp(4,3) PWC6228: #{…} not allowed in a template text body.


4) Add commons-el.jar/log4j.jar to WEB-INF\lib if not present

5)Make sure FacesServlet/StartupContextListener is setup as per myfaces 1.1 deployment

   <?xml version="1.0" encoding="UTF-8"?>
        <web-app version="2.3">
       ….
       <!– Listeners –>
   <listener>
      <listener-class>
         org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
   </listener>
   
   
   <servlet>
      <servlet-name>Faces Servlet</servlet-name>
      <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>

          <servlet-mapping>
      <servlet-name>Faces Servlet</servlet-name>
      <url-pattern>/faces/*</url-pattern>
   </servlet-mapping>
   ….

chndu6ue
Champ in-the-making
Champ in-the-making
Continued….
Add log4j.properties to WEB-INF\classes to view the logs