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

kevinr
Star Contributor
Star Contributor
Thankyou for posting this detailed information. FYI for Alfresco 2.1 we have moved to MyFaces1.1.5 which fixes some of the issues you mention (such as acceptcharset form attribute). We still have some dependancies on MyFaces impl which we'll look at removing.

Thanks,

Kevin

pcheipe
Champ in-the-making
Champ in-the-making
We are trying the same: install an Alfresco 2.0 over a Glassfish 2.0.

Our a server is a 64 Bit Debian.

I confirm that the first problem is the "OutOfMemory genPerm error".

The "-XX:MaxPermSize=128m" JVM parameter fixes it perfectly (thanks !).



But, before facing JSF problems we are facing another one. The server seems not to be able to parse the web.xml file.

It looks like it tries to access an external resource (as on old Weblogic servers which were searching for the DTD on the web). Our server, as many other, cannot access anything else than the database.

The error log are the following:

(…)
[#|2007-03-13T23:11:34.858+0100|INFO|sun-appserver-pe9.0|javax.enterprise.resource.webcontainer.jsf.config|_ThreadID=10;_ThreadName=main;;|Completed initializing Sun's JavaServer Faces implementation (1.2_02-b03-FCS) for context ''|#]

[#|2007-03-13T23:14:46.407+0100|INFO|sun-appserver-pe9.0|javax.enterprise.system.stream.out|_ThreadID=10;_ThreadName=main;|23:14:46,401 FATAL [webapp.webxml.WebXmlParser] Unable to parse web.xml
java.net.ConnectException: Connection timed out
   at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
   at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:527)
   (…)
   at org.apache.myfaces.webapp.webxml.WebXmlParser.parse(WebXmlParser.java:89)
   at org.apache.myfaces.webapp.webxml.WebXml.init(WebXml.java:135) (…)
I am downloading source code to try to understand what it is trying to access.

Standard "WebXmlParsers" usually only use the dtd name as a key.

Have an idea ?

kevinr
Star Contributor
Star Contributor
The only external reference is a pretty standard dtd url at the start of the file:

<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">

Thanks,

Kev

pcheipe
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…

pcheipe
Champ in-the-making
Champ in-the-making
Next problem: Web App is not starting yet.

The log is:

[#|2007-03-14T20:19:59.032+0100|SEVERE|sun-appserver-pe9.0|javax.enterprise.system.container.web|_ThreadID=10;_ThreadName=main;_RequestID=db65bcad-928d-42fb-86c3-15880b0b0d7a;|WebModule[/alfresco]Exception sending context initialized event to listener instance of class com.sun.faces.config.ConfigureListener
javax.faces.FacesException: java.net.MalformedURLException: Path WEB-INF/faces-config-custom.xml does not start with a "/" character
        at com.sun.faces.config.ConfigureListener.getContextURLForPath(ConfigureListener.java:1638)
 

This times it sounds like it is an Alfresco bug. Look at the web.xml file. A "/" is missing:

<param-name>javax.faces.CONFIG_FILES</param-name>
  <param-value>/WEB-INF/faces-config-app.xml,/WEB-INF/faces-config-beans.xml,/WEB-INF/faces-config-navigation.xml,/WEB-INF/faces-config-common.xml,/WEB-INF/faces-config-repo.xml,/WEB-INF/faces-config-wcm.xml,WEB-INF/faces-config-custom.xml,/WEB-INF/faces-config-enterprise.xml</param-value>
  </context-param>

stop / start … still problems

pcheipe
Champ in-the-making
Champ in-the-making
Oh yes, on Linux, ports with small numbers cannot be opened by another user than root.

The server crashed on opening FTP or NetBIOS port.

Using root to stop / start the server solved the problem.

I've still got one.

[#|2007-03-14T20:52:32.718+0100|SEVERE|sun-appserver-pe9.0|javax.enterprise.system.container.web|_ThreadID=12;_ThreadName=httpWorkerThread-8080-1;_RequestID=7ea54b2a-acdd-4ba0-9f3e-eb1b3b6c5ad7;|StandardWrapperValve[Faces Servlet]: Servlet.service() for servlet Faces Servlet threw exception
java.lang.UnsupportedOperationException
        at javax.faces.application.Application.getELResolver(Application.java:443)
        at com.sun.faces.context.FacesContextImpl.getELContext(FacesContextImpl.java:174)

I perhaps missed something in Nick's conf…

kevinr
Star Contributor
Star Contributor
Next problem: Web App is not starting yet.

The log is:

[#|2007-03-14T20:19:59.032+0100|SEVERE|sun-appserver-pe9.0|javax.enterprise.system.container.web|_ThreadID=10;_ThreadName=main;_RequestID=db65bcad-928d-42fb-86c3-15880b0b0d7a;|WebModule[/alfresco]Exception sending context initialized event to listener instance of class com.sun.faces.config.ConfigureListener
javax.faces.FacesException: java.net.MalformedURLException: Path WEB-INF/faces-config-custom.xml does not start with a "/" character
        at com.sun.faces.config.ConfigureListener.getContextURLForPath(ConfigureListener.java:1638)
 

This times it sounds like it is an Alfresco bug. Look at the web.xml file. A "/" is missing:

<param-name>javax.faces.CONFIG_FILES</param-name>
  <param-value>/WEB-INF/faces-config-app.xml,/WEB-INF/faces-config-beans.xml,/WEB-INF/faces-config-navigation.xml,/WEB-INF/faces-config-common.xml,/WEB-INF/faces-config-repo.xml,/WEB-INF/faces-config-wcm.xml,WEB-INF/faces-config-custom.xml,/WEB-INF/faces-config-enterprise.xml</param-value>
  </context-param>

stop / start … still problems

Yep this was a bug fixed in HEAD recently.

Kevin

kevinr
Star Contributor
Star Contributor
Oh yes, on Linux, ports with small numbers cannot be opened by another user than root.

The server crashed on opening FTP or NetBIOS port.

Using root to stop / start the server solved the problem.
Yes i think you need to start the server as a user with the appropriate rights to open those ports - that's not a bug.

I've still got one.

[#|2007-03-14T20:52:32.718+0100|SEVERE|sun-appserver-pe9.0|javax.enterprise.system.container.web|_ThreadID=12;_ThreadName=httpWorkerThread-8080-1;_RequestID=7ea54b2a-acdd-4ba0-9f3e-eb1b3b6c5ad7;|StandardWrapperValve[Faces Servlet]: Servlet.service() for servlet Faces Servlet threw exception
java.lang.UnsupportedOperationException
        at javax.faces.application.Application.getELResolver(Application.java:443)
        at com.sun.faces.context.FacesContextImpl.getELContext(FacesContextImpl.java:174)

I perhaps missed something in Nick's conf…

Not sure about this one Smiley Sad

Kevin

pcheipe
Champ in-the-making
Champ in-the-making
pcheipe wrote:
Oh yes, on Linux, ports with small numbers cannot be opened by another user than root.

The server crashed on opening FTP or NetBIOS port.

Using root to stop / start the server solved the problem.

Yes i think you need to start the server as a user with the appropriate rights to open those ports - that's not a bug.

Clearly not. It was just a reminder for the ones like me that forget it too fast Smiley Wink .