Tomcat Installation

Version 28.3 by Jesse Bright on 2017/02/28

Installation Steps

The Tomcat project has brought a change in the way they handle RequestDispatcher which has caused regressions in XWiki for some versions of Tomcat. Thus you should not use the following Tomcat versions:

  • >= 9.0.0.M5 and < 9.0.0.M10 for the 9.0.x branch (fixed in 9.0.0.M10)
  • >= 8.5.1 and < 8.5.5 for the 8.5.x branch (fixed in 8.5.5)
  • >= 8.0.34 and < 8.0.37 for the 8.0.x branch (fixed in 8.0.37)
  • >= 7.0.70 and < 7.0.71 for the 7.0.x branch (fixed in 7.0.71)
  • Download and install Tomcat. It's usually as simple as unzipping it in a directory. Let's call this directory TOMCAT_HOME.
  • Extract the XWiki WAR into a directory named xwiki in TOMCAT_HOME/webapps/. The reason you're expanding the WAR is because you'll need to modify one configuration file from inside the WAR later on when you configure the database access.
  • Edit your conf/server.xml to set UTF-8 encoding: <Connector port="8080" ... URIEncoding="UTF-8"/>
  • Make sure you give enough memory to Java since by default Tomcat is configured with not enough memory for XWiki.

Activate headless mode

If you're operating XWiki on a Linux server with no X11 libraries installed you have to enable headless mode for your Tomcat installation. Sometimes this is also needed on Windows platforms. Typical exceptions are:

  • Exception: Could not initialize class sun.awt.X11.XToolkit
  • java.lang.InternalError: Can't connect to X11 window server using 'localhost:10.0' as the value of the DISPLAY variable
  • On Linux create a file /TOMCAT_HOME/bin/setenv.sh and insert the following code:
    #!/bin/sh
    export JAVA_OPTS="${JAVA_OPTS} -Djava.awt.headless=true"
  • On Windows create a file /TOMCAT_HOME/bin/setenv.bat and insert the following code:
    set JAVA_OPTS=%JAVA_OPTS% -Djava.awt.headless=true
  • When running as a Windows service the setenv.bat is not working. See registry HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Procrun 2.0\FOOBAR\Parameters\Java for similar settings.

Optional configuration

  • Edit your conf/server.xml to enable gzip compression: <Connector port="8080" ... compression="on" compressionMinSize="2048" compressableMimeType="text/html,text/xml,text/css,text/javascript,application/x-javascript"/>
  • If you want to modify the port on which Tomcat will run, edit TOMCAT_HOME/conf/server.xml/. Search for 8080 (sometimes 8180 if you are under Linux) and replace with the port value you wish to use.
  • It is possible to setup a Tomcat Java Server as a UNIX Daemon - JSVC. Just follow these instructions. The only reason to make Tomcat a daemon is to make it runnable on the 80th port, which can be replaced by using NginX as a proxy on the 80th port and then forwarding to Tomcat to the 8080th port.

Policy configuration

For those who activate the security manager for Tomcat, add this portion of code to the end of your conf/catalina.policy file from your Tomcat installation. You can adapt the code for the available installations of OpenOffice/LibreOffice on your server and for different databases :

grant codeBase "file:${catalina.base}/webapps/xwiki/WEB-INF/lib/-" {
 // for mySQL connection
 permission java.net.SocketPermission "127.0.0.1:3306", "connect,resolve";

 // XWiki must have access to all properties in read/write
 permission java.util.PropertyPermission "*", "read, write";

 // Generic detected permissions
 permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
 permission java.lang.RuntimePermission "createClassLoader";
 permission java.lang.RuntimePermission "setContextClassLoader";
 permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.loader";
 permission java.lang.RuntimePermission "accessDeclaredMembers";
 permission java.lang.RuntimePermission "getenv.ProgramFiles";
 permission java.lang.RuntimePermission "getenv.APPDATA";
 permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
 permission java.lang.RuntimePermission "getClassLoader";
 permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.connector";
 permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.util.threads";
 permission java.lang.RuntimePermission "reflectionFactoryAccess";
 permission java.lang.RuntimePermission "accessClassInPackage.com.sun.jmx.interceptor";
 permission java.lang.RuntimePermission "accessClassInPackage.com.sun.jmx.mbeanserver";
 permission java.lang.RuntimePermission "modifyThread";
 permission java.lang.RuntimePermission "getProtectionDomain";

 // JAXB permissions
 permission javax.xml.bind.JAXBPermission "setDatatypeConverter";

 // Serialization related permissions
 permission java.io.SerializablePermission "allowSerializationReflection";
 permission java.io.SerializablePermission "creator";
 permission java.io.SerializablePermission "enableSubclassImplementation";

 // Internal resources access permissions
 permission java.io.FilePermission "synonyms.txt", "read";
 permission java.io.FilePermission "lang/synonyms_en.txt", "read";
 permission java.io.FilePermission "quartz.properties", "read";
 permission java.io.FilePermission "/templates/-", "read";
 permission java.io.FilePermission "/skins/-", "read";
 permission java.io.FilePermission "/resources/-", "read";

 // MBean related permissions
 permission javax.management.MBeanServerPermission "createMBeanServer";
 permission javax.management.MBeanPermission "*", "registerMBean";
 permission javax.management.MBeanPermission "*", "unregisterMBean";
 permission javax.management.MBeanTrustPermission "register";
 permission javax.management.MBeanPermission "-#-[-]", "queryNames";
 permission javax.management.MBeanServerPermission "findMBeanServer";

 // LibreOffice/OpenOffice related permissions
 permission java.io.FilePermission "/opt/openoffice.org3/program/soffice.bin", "read";
 permission java.io.FilePermission "/opt/libreoffice/program/soffice.bin", "read";
 permission java.io.FilePermission "/usr/lib/openoffice/program/soffice.bin", "read";
 permission java.io.FilePermission "/usr/lib/libreoffice/program/soffice.bin", "read";

 // Allow file storage directory reading - for directory and everything underneath
 // This is dependent on the setting of environment.permanentDirectory in xwiki.properties
 permission java.io.FilePermission "${catalina.base}${file.separator}xwikidata${file.separator}", "read,write,delete";
 permission java.io.FilePermission "${catalina.base}${file.separator}xwikidata${file.separator}-", "read,write,delete";

 // Allow file storage directory reading - temporary directory and everything underneath
 // This is dependent on the setting of environment.temporaryDirectory in xwiki.properties.
 permission java.io.FilePermission "${catalina.base}${file.separator}temp${file.separator}", "read,write,delete";
 permission java.io.FilePermission "${catalina.base}${file.separator}temp${file.separator}-", "read,write,delete";
};

Please note that this policy configuration file have been tested on CentOS 5.9 with Sun JDK 1.7.0u21 on Tomcat 7.0.40 with XWiki 5.0.1 installed.

Nginx proxying for Tomcat applications

As Tomcat is not a true web server, it's worth to use it as backend. Nginx is one of the best solutions for the frontend web server.

So, after a typical XWiki installation we have XWiki running on http://localhost:8080/xwiki. Most probably, we want to access XWiki via http://mydomain.com on standard 80 port. Tuning Nginx will give us the desired result:

  • create this file /etc/nginx/conf.d/tomcat.conf
  • put the following code inside:
    server {
       listen       80;
       server_name  mydomain.com;
        # Root to the XWiki application
       root /opt/tomcat/webapps/xwiki;

       location / {
            #All "root" requests will have /xwiki appended AND redirected to mydomain.com again
           rewrite ^ $scheme://$server_name/xwiki$request_uri? permanent;
        }

       location ^~ /xwiki {
           # If path starts with /xwiki - then redirect to backend: XWiki application in Tomcat
           # Read more about proxy_pass: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
          proxy_pass http://localhost:8080;
          proxy_set_header        X-Real-IP $remote_addr;
          proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header        Host $http_host;
          proxy_set_header        X-Forwarded-Proto $scheme;
        }
    }
  • restart nginx

Now all http://mydomain.com/* requests will lead to the XWiki application. Please note that these settings are basic. For more flexible solutions please refer to the Nginx documentation

HTTPS setting

  • If using HTTPS for accessing XWiki, several modifications have to be made to ensure flawless functionality. Since urls are generated from relative path (/xwiki/bin/show/Space/Page), Tomcat has to know which protocol to use, otherwise JSON requests with redirect fails (attachment uploads, extension updating, etc.)
  • Modify connector (in server.xml) to <Connector port="8080" ... secure="true" scheme="https" />
  • Modify host (in server.xml) and add Remote Ip Valve <Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="x-forwarded-for" protocolHeader="x-forwarded-proto" /> (only needed if using another server for HTTPS)

If using another server as a HTTPS proxy (such as Nginx or Apache httpd), X-Forwarded-For and X-Forwarded-Proto headers have to be set!

Troubleshooting

Out Of Memory Error

When you run XWiki in Tomcat with the default settings, you'll probably get an Out Of Memory error (java.lang.OutOfMemoryError: Java heap space or java.lang.OutOfMemoryError: PermGen space) since the default Tomcat memory settings are not enough for XWiki Memory Requirements. You'll need to allocate more memory to the JVM. 

One easy solution to configure Tomcat's memory is to create a setenv.sh file (or setenv.bat on Windows) in [TOMCAT_HOME]/bin/ (where [TOMCAT_HOME] is where you've installed Tomcat) and inside this file add the following (adjust the memory values according to the XWiki Memory Requirements). For example:

CATALINA_OPTS="-Xmx1024m -XX:MaxPermSize=192m"

On most Linux distributions, this can also be achieved in /etc/tomcatX/tomcatX.conf or /etc/conf.d/tomcatX.conf (where X is the version of Tomcat installed).

On Windows, if you are running Tomcat as a service then defining CATALINA_OPTS will not help. There is an utility provided in the bin folder of your Tomcat installation (for example for Tomcat 5.x on Windows it's called tomcat5w.exe). It's a GUI tool which can be used to set various options including the heap size.

Java Security Manager

By default Tomcat is configured to have the Java Security Manager turned on. See the sample policy file for more details.

If you want to turn off the Java Security Manager for Tomcat, edit the Tomcat startup script. You might also want to check your /etc/init.d/tomcat file or /etc/default/tomcat5.5. You should see the following code:

# Use the Java security manager? (yes/no)
TOMCAT5_SECURITY=

Set it to no to turn off the Security Manager.

Allowing "/" in page names

Tomcat completely freaks out when there's a %2F in URLs and it's not something that can be changed in XWiki. See this note for more information.

You can configure Tomcat to allow this, by enabling :

org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH

Note that if you're using Apache you also need to configure Apache to allow encoded / and \.

NotSerializableException

If you get the following:

SEVERE: IOException while loading persisted sessions: java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: org.xwiki.model.internal.reference.LocalStringEntityReferenceSerializer
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: org.xwiki.model.internal.reference.LocalStringEntityReferenceSerializer
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.defaultReadFields(Unknown Source)

This means that on startup Tomcat tries to load saved Sessions and fails to do so. In this case it fails because some non-serializable object was put in the Servlet Session. To work around the issue you can tell Tomcat to not save sessions.

SEVERE: Error listenerStart

If you get this error in your Tomcat logs then you'll need to enable finer-grained logging configuration to see what's the problem. For Tomcat 6.x/7.x this involves copying the following content in a WEB-INF/classes/logging.properties file:

org.apache.catalina.core.ContainerBase.[Catalina].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].handlers = java.util.logging.ConsoleHandler
Tags:
   

Get Connected