====== [[http://tomcat.apache.org/|Tomcat application server]] ======
===== Security =====
==== Using LDAP server for BASIC authentication ====
In this setup we will use the office-wide LDAP authentication server to authenticate the client using HTTP basic authentication (digest will not work).
First of all discover the structure of LDAP directory. You need to know the LDAP server URL, DN prefix for user and group search:
$ ldapsearch -H ldap://ldap.company.org:389/ -D uid=myuid,ou=people,dc=company,dc=org -w -b 'uid=myuid,ou=people,dc=company,dc=org'
dn: uid=myuid, ou=people, dc=company, dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: myuid
cn: Dmitry Katsubo
sn: Katsubo
givenname: Dmitry
displayname: Dmitry Katsubo
...
For group (role) search we will use the following filter:
$ ldapsearch -H ldap://ldap.company.org:389/ -D uid=myuid,ou=people,dc=company,dc=org -w -b 'ou=groups,dc=company,dc=org' -s sub '(member=uid=myuid,ou=people,dc=company,dc=org)'
dn: cn=subdiv5587, ou=groups, dc=company, dc=org
objectclass: top
objectclass: groupOfNames
cn: subdiv5587
description: Subdevision 55.87
member: uid=myuid, ou=people, dc=company, dc=org
... other members ...
dn: cn=div55, ou=groups, dc=company, dc=org
objectclass: top
objectclass: groupOfNames
cn: div55
description: Devision 55
member: uid=myuid, ou=people, dc=company, dc=org
... other members ...
Based on the discovered information we define in Tomcat's ''server.xml'' the following [[tomcat>realm-howto.html|realm]]((Check another Tomcat configuration example for LDAP authentication [[stackoverflow>267869|here]])):
...
This combined realm uses the local user database (e.g. you want to define local Tomcat admins or application deployers) as well as the LDAP directory to authenticate. The last one applies authentication-by-binding mechanism. If want client to check the password, use ''userSearch'' + ''userSubtree'' ''[[tomcat>api/org/apache/catalina/realm/JNDIRealm.html|JNDIRealm]]'' properties.
Now you can say in application's ''WEB-INF/web.xml'':
...
All Pages
/*
GET
POST
dir2711
The role that is assigned to all members of Subdevision 55.87.
subdiv5587
BASIC
MyApplication
You can define several ''''s and several ''''s in ''''. The '''' from '''' should be also described by ''''.
'''' represents basic HTTP/1.1 authentication methods:
* BASIC, DIGEST -- described in [[rfc>2617]]
* NEGOTIATE -- described in [[rfc>4559]]
* FORM -- means the credentials should be entered via HTML form defined by '''' element((See [[http://jcp.org/aboutJava/communityprocess/first/jsr154/index3.html|Java Servlet 2.4 Specification, §12.5 "Authentication"]] for more details about authentication methods and roles configuration)).
In the code one can use [[javaee>api/javax/servlet/http/HttpServletRequest.html#getRemoteUser()|HttpServletRequest#getRemoteUser()]] and [[javaee>api/javax/servlet/http/HttpServletRequest.html#isUserInRole(java.lang.String)|HttpServletRequest#isUserInRole()]] methods:
package org.company.application.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class MyWebController {
private static final Log logger = LogFactory.getLog(MyWebController.class);
@RequestMapping(value = "/processFile", method = RequestMethod.POST)
public void processFile(HttpServletRequest request, HttpServletResponse response)
{
logger.debug("User:" + request.getRemoteUser() + ", is in directorate:" + request.isUserInRole("subdiv5587"));
...
}
}
Let's test the above declared POST request handler:
$ wget -S -nv -t 1 --post-file myfile.txt -O - http://myuid:mypasword@service-id.company.org:8080/application/processFile
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
WWW-Authenticate: Basic realm="MyApplication"
Content-Type: text/html;charset=utf-8
Content-Length: 954
Date: Thu, 05 Aug 2010 16:00:40 GMT
Connection: keep-alive
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/plain;charset=US-ASCII
Content-Length: 3999
Date: Thu, 05 Aug 2010 16:01:09 GMT
Connection: keep-alive
In a log file:
DEBUG [org.apache.catalina.authenticator.AuthenticatorBase] Security checking request POST /application/processFile
DEBUG [org.apache.catalina.realm.RealmBase] Checking constraint 'SecurityConstraint[All Pages]' against POST /processFile --> true
DEBUG [org.apache.catalina.authenticator.AuthenticatorBase] Calling hasUserDataPermission()
DEBUG [org.apache.catalina.realm.RealmBase] User data constraint has no restrictions
DEBUG [org.apache.catalina.authenticator.AuthenticatorBase] Calling authenticate()
DEBUG [org.apache.catalina.realm.CombinedRealm] Attempting to authenticate user "myuid" with realm "org.apache.catalina.realm.UserDatabaseRealm/1.0"
DEBUG [org.apache.catalina.realm.CombinedRealm] Cannot find message associated with key combinedRealm.authFail
DEBUG [org.apache.catalina.realm.CombinedRealm] Attempting to authenticate user "myuid" with realm "org.apache.catalina.realm.JNDIRealm/1.0"
DEBUG [org.apache.catalina.core.ContainerBase.[Catalina]] Found role: div55
DEBUG [org.apache.catalina.core.ContainerBase.[Catalina]] Found role: subdiv5587
DEBUG [org.apache.catalina.realm.CombinedRealm] Authenticated user "myuid" with realm "org.apache.catalina.realm.JNDIRealm/1.0"
DEBUG [org.apache.catalina.authenticator.AuthenticatorBase] Authenticated 'myuid' with type 'BASIC'
DEBUG [org.apache.catalina.authenticator.AuthenticatorBase] Calling accessControl()
DEBUG [org.apache.catalina.realm.RealmBase] Checking roles GenericPrincipal[myuid(div55,subdiv5587)]
DEBUG [org.apache.catalina.realm.RealmBase] Different realm org.apache.catalina.realm.CombinedRealm@1d32e45 org.apache.catalina.realm.JNDIRealm@12f1bf0
DEBUG [org.apache.catalina.realm.RealmBase] Username myuid has role subdiv5587
DEBUG [org.apache.catalina.realm.RealmBase] Role found: subdiv5587
DEBUG [org.apache.catalina.authenticator.AuthenticatorBase] Successfully passed all security constraints
DEBUG [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] Mapping [/processFile] to handler 'org.company.application.web.MyWebController@24f4eb'
DEBUG [org.company.application.web.MyWebController] User:myuid, is in directorate:true
For more information see [[tomcat>realm-howto.html|Realm Configuration HOWTO]].
==== Using NEGOTIATE authentication ====
General installation steps:
* Create ''/etc/krb5.conf'' (or use the system-wide one, defined by Linux administrator):
[libdefaults]
default_realm = REALM.COMPANY.ORG
default_tkt_enctypes = des-cbc-md5 des-cbc-crc
default_tgs_enctypes = des-cbc-md5 des-cbc-crc
kdc_timesync = 0
kdc_default_options = 0x40000010
clockskew = 300
check_delegate = 0
ccache_type = 3
kdc_timeout = 60
[domain_realm]
company.org = REALM.COMPANY.ORG
.company.org = REALM.COMPANY.ORG
[realms]
REALM.COMPANY.ORG = {
admin_server = server1.company.org
kdc = server1.company.org
kdc = server2.company.org
}
* Additionally to the following [[http://spnego.sourceforge.net/spnego_tomcat.html|installation instructions]], use this:
* Download the ''[[https://sourceforge.net/projects/spnego/files/|spnego.jar]]'' library and put it to ''/usr/share/tomcat6/lib''
* Add the following to ''/etc/tomcat6/web.xml'' (or to your application ''web.xml''):
...
SpnegoHttpFilter
net.sourceforge.spnego.SpnegoHttpFilter
spnego.allow.basic
true
spnego.allow.localhost
true
spnego.allow.unsecure.basic
true
spnego.krb5.conf
/etc/krb5.conf
spnego.login.conf
/etc/tomcat6/login.config
spnego.login.client.module
spnego-client
spnego.login.server.module
spnego-server
spnego.prompt.ntlm
true
spnego.logger.level
1
SpnegoHttpFilter
*
* Create ''/etc/tomcat6/login.config'', which consists of two sections: ''spnego-client'' is used to authenticate service client (browser), ''spnego-server'' is used to authenticate service (Tomcat) to KDC. The service principal should be present in a given ''/etc/tomcat6/service.keytab'' and should be provided to you by KDC administrator:
spnego-client {
com.sun.security.auth.module.Krb5LoginModule required;
};
spnego-server {
com.sun.security.auth.module.Krb5LoginModule required
storeKey=true
useKeyTab=true
keyTab="file:/etc/tomcat6/service.keytab"
principal="HTTP/service-id.company.org@REALM.COMPANY.ORG";
};
* Now you can upload [[http://spnego.sourceforge.net/hello_spnego.zip|hello_spnego.jsp]] to ''/var/lib/tomcat6/webapps/ROOT'' and test by navigating to ''http://service-id.company.org:8080/hello_spnego.jsp''.
''net.sourceforge.spnego.SpnegoHttpFilter'' uses JUL to log debug information. See [[#how_to_enable_log4j_logging_for_tomcat|Questions Answered]] section for the hints about how to setup the logging environment.
To setup ''net.sourceforge.spnego.SpnegoHttpFilter'' for Jetty, refer [[http://wiki.openbluedragon.org/wiki/index.php/Jetty:ConfiguringSSO|Configuring SSO on Jetty 6]]. The only thing to add to above settings is the following:
REALM.COMPANY.ORG
spnego-client
For Jetty see [[jetty#how_to_configure_jetty_to_use_spnegonegotiate_authentication|How to configure Jetty to use SPNEGO/NEGOTIATE authentication]]. \\
For local services development, follow [[conflepo>RNA/spnego-Tomcat|SPNEGO Tomcat instructions]]:
* Upload ''xxx-spnego-1.1.20.jar''((Provides ''XmiRoleMappingLoginModule'' module, that is responsible for mapping users to security roles using the mapping file ''application-bnd.xmi'')), ''xxx-spnego-tomcat-1.1.20.jar'', ''xxx_common_Jaas-0.3.3.jar'', ''xxx-spnego-pac-1.1.20.jar''((Provides the support of [[http://appliedcrypto.com/spnego/pac/ms_kerberos_pac.html|Microsoft Kerberos Extension called PAC]] (Privilege Attribute Certificate))), ''[[http://mirrors.ibiblio.org/pub/mirrors/maven2/bouncycastle/bcprov-jdk16/140/bcprov-jdk16-140.jar|bcprov-jdk16-1.40.jar]]''(([[http://www.bouncycastle.org/|Bouncy Castle Crypto]] package -- a Java implementation of cryptographic symmetric block algorithms (AES, Blowfish, CASTx, DES, IDEA, RCx, Rijndael, ...), symmetric stream algorithms (RC4, HCx, Grain, ...), asymmetric block algorithms (OAEP, PCKS1, ...) and digest algorithms(MDx, SHAx, RipeMD, Tiger, ...))), ''commons-logging-1.1.1.jar'' libraries to ''/usr/share/tomcat6/lib''.
* Create ''/etc/tomcat6/login.config'', which consists of two sections: ''app.spnego.client'' is used to authenticate service client (browser), ''app.spnego.server'' is used to authenticate service (Tomcat) to KDC. The service principal should be present in a given ''/etc/tomcat6/service.keytab'' and should be provided to you by KDC administrator:
// SPNEGO setup to authenticate the client. Should match context.xml/Context/Realm[className='org.company.security.tomcat.SpnegoRealm']/@AppName:
app.spnego.client {
org.company.security.sso.spnego.SpnegoLoginModule required;
// org.company.security.sso.spnego.XmiRoleMappingLoginModule optional
// additionalRoles="additionalRoleA,additionalRoleB,Authenticated";
};
// SPNEGO setup to authenticate the sevice to KDC.
// The given keytab should correspond to principal name and should be registered at KDC.
app.spnego.server {
com.sun.security.auth.module.Krb5LoginModule required
principal="HTTP/service-id.company.org@REALM.COMPANY.ORG"
useKeyTab=true
keyTab="/etc/tomcat6/service.keytab"
storeKey=true
debug=true;
};
* Create ''/etc/tomcat6/spnego.properties'' that should contain the references to ''login.config'' and ''krb5.conf''. This file is read by ''xxx-spnego-1.1.20.jar'':
java.security.auth.login.config=/etc/tomcat6/login.config
java.security.krb5.conf=/etc/krb5.conf
jaas.kerberos.config.name=app.spnego.server
# Settings below are optional and required for users-to-roles mappings. You need to enable XmiRoleMappingLoginModule in login.config.
#xxx.ldap.url=ldap://server1.company.org:389/dc=company,dc=org
#bindings.file.name=/etc/tomcat6/application-bnd.xmi
#roles.file.name=conf/etc/tomcat6/application.xml
* Include ''/etc/tomcat6/spnego.properties'' into server ''JAVA_OPTS'':
# Enable SPNEGO
JAVA_OPTS="${JAVA_OPTS} -Dspnego.config=/etc/tomcat6/spnego.properties"
* Modify '''' of application's ''WEB-INF/web.xml'':
...
...
*
NEGOTIATE
MyApplication
* Create application ''META-INF/context.xml'' or modify server-wide '''':
* :OPT: Create ''/etc/tomcat6/application-bnd.xmi'' and ''/etc/tomcat6/application.xml'' to customize the mapping between LDAP groups and Web Container roles:
My Enterprise Application
My Service
myservice.war
production/myservice
System Administrator
SYSADMIN
Online Operator
OPERATOR
All Authenticated Users
AUTHENTICATED_USER
===== Questions answered =====
=== Tomcat cannot start due to ''java.net.SocketException'' ===
The following error is in server log file:
SEVERE: StandardServer.await: create[8005]:
java.net.SocketException: Invalid argument
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:365)
at java.net.ServerSocket.bind(ServerSocket.java:319)
at java.net.ServerSocket.(ServerSocket.java:185)
at org.apache.catalina.core.StandardServer.await(StandardServer.java:373)
at org.apache.catalina.startup.Catalina.await(Catalina.java:662)
at org.apache.catalina.startup.Catalina.start(Catalina.java:614)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
Start your JVM with ''-Djava.net.preferIPv4Stack=true'' (see [[javase>/docs/guide/net/properties.html|Java Networking Properties]]) or set ''net.ipv6.bindv6only'' kernel system variable to zero (see [[http://lists-archives.org/debian-user/3550442-tomcat-is-only-listening-with-ip6-and-not-ip4.html|this conversion]]):
# This sysctl sets the default value of the IPV6_V6ONLY socket option.
#
# When disabled, IPv6 sockets will also be able to send and receive IPv4
# traffic with addresses in the form ::ffff:192.0.2.1 and daemons listening
# on IPv6 sockets will also accept IPv4 connections.
#
# When IPV6_V6ONLY is enabled, daemons interested in both IPv4 and IPv6
# connections must open two listening sockets.
# This is the default behaviour of all modern operating systems.
net.ipv6.bindv6only = 0
=== The form fields values submitted by a browser are not correctly UTF-8 encoded ===
From [[apache>tomcat/FAQ/CharacterEncoding|Character Encoding Issues]]:
For correct UTF-8 URL handling set ''%%'' option in ''server.xml'' or use ''%%''.
The contents (request body) is not correctly represented because by default the character encoding of ''HttpServletRequest'' is set to ISO-8859-1 (unless is provided in browser request). Spring has a special ''CharacterEncodingFilter'' filter that fixes this (see sample [[stackoverflowa>3228524/267197|here]]).
=== ''Unable to add the resource at [/...] to the cache for web application [/app] because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache'' ===
To fix this add:
...
=== How to specify the context path for application deployment in Tomcat? ===
Before Tomcat 6 the context path could have been specified in ''META-INF/context.xml''
however this behaviour has changed in Tomcat 6 (see [[http://tomcat.apache.org/tomcat-6.0-doc/config/context.html|Context Container]], [[apachebztracker>46713|bug#46713]] and [[stackoverflow>6623586|Tomcat's context path for a webapp not working]]):
''path'' attribute must only be used when statically defining a Context in ''server.xml''. In all other circumstances, the path will be inferred from the filenames used for either the .xml context file or the ''docBase''.
For deployment to Tomcat 6 you should use ''tomcat-maven-plugin'' (that deploys via [[http://tomcat.apache.org/tomcat-6.0-doc/manager-howto.html|Tomcat Manager]]):
org.codehaus.mojo
tomcat-maven-plugin
tomcat-server-id
${tomcat.server.url}/manager
${context.path}
=== Why ImageIO library does not work when deployed to Tomcat AS? ===
The problem is correctly described in [[https://bugs.launchpad.net/goobi-production/+bug/788160/comments/13|comment #13 for bug 788160 (Error reading in TIFF images)]]:
Tomcat has build-in [[http://tomcat.apache.org/tomcat-6.0-doc/config/listeners.html#JRE_Memory_Leak_Prevention_Listener_-_org.apache.catalina.core.JreMemoryLeakPreventionListener|memory leak protections]], one of which does not allow to automatically image providers from web application in JVM-wide ImageIO registry. This is done by [[grepcode>repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/catalina/core/JreMemoryLeakPreventionListener.java#139|JreMemoryLeakPreventionListener]] which initializes ImageIO (call to any static method forces static registry to be initialized).
As a workaround ''appContextProtection'' has to be disabled for ''JreMemoryLeakPreventionListener'':
however this is not a complete solution as if application is redeployed again and again, the references to image providers will still be kept together with classloader and all classes it has loaded. This will cause [[https://blogs.oracle.com/jonthecollector/entry/presenting_the_permanent_generation|PermGen]] to run out of memory and under certain conditions may cause [[https://groups.google.com/forum/#!msg/google-web-toolkit/QvduX97Swfg/Bv1V4NPI03cJ|ClassCastException when using ImageIO]].
One solution is provided in ''[[github>haraldk/TwelveMonkeys/blob/master/servlet/src/main/java/com/twelvemonkeys/servlet/image/IIOProviderContextListener.java|IIOProviderContextListener.java]]'' (see [[stackoverflowa>17365294/267197|How to resolve OutOfMemoryError with ImageIO plugins as the cause]]), and basically consists of the following steps:
* Web application needs to call ''ImageIO.scanForPlugins()'' before using any ImageIO API (servlet initialization).
* On destruction, web application needs to deregister providers loaded from web application classpath.
Another solution is to put ''jai_imageio.jar'' + ''jai_codec.jar'' into server-wide ''lib/'' folder.
References:
* [[stackoverflowa>18141946/267197|My Java SPI extension is not loaded]]
* [[http://tomcat.10.x6.nabble.com/Problems-with-ImageIO-td2073212.html#a2073223|ImageIO.getImageReadersByFormatName("tiff") returns false for hasNext()]]
* [[http://thejavashop.net/blog/?p=27|JAI Imaging and Tomcat]]
=== How to enable ''log4j'' logging for Tomcat? ===
See steps [[tomcat>logging.html#log4j|here]]. Recommended Log4j configuration:
log4j.rootLogger=INFO, R
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=${catalina.base}/logs/tomcat.log
log4j.appender.R.MaxFileSize=50MB
log4j.appender.R.MaxBackupIndex=5
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{dd.MM HH:mm:ss} %-5p [%c] %m%n
# For a more detailed Catalina localhost log, uncomment below:
#log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost]=DEBUG
#log4j.logger.org.apache.catalina.core=DEBUG
#log4j.logger.org.apache.catalina.session=DEBUG
If you remove ''/etc/tomcat6/logging.properties'' file you will not be able to see the debug output done via ''java.util.logging''. So either keep it, or remove/rename and continue with steps below.
Also you might be interested in redirecting the ''java.util.logging'' to Log4j completely so you don't need to dig two log files for errors as everything will be in one file. For that you need to do further steps to one mentioned above:
* Download [[http://people.apache.org/~psmith/logging.apache.org/sandbox/jul-log4j-bridge/intro.html|jul-log4j-bridge]] from [[http://people.apache.org/~psmith/logging.apache.org/repo/org/apache/logging/apache-jul-log4j-bridge/1.0.0-SNAPSHOT/apache-jul-log4j-bridge-1.0.0-20080915.045446-7.jar|here]] and put it to ''/usr/share/tomcat6/lib''.
* Make sure you have [[http://logging.apache.org/log4j/|Log4j]] implementation (e.g. ''log4j-1.2.15.jar'') in ''/usr/share/tomcat6/lib''.
* Include ''apache-jul-log4j-bridge.jar'', ''log4j-1.2.15.jar'' and ''log4j.properties'' directory location into Tomcat boot classpath:
--- catalina.sh.orig 2010-06-14 21:21:36.000000000 +0200
+++ catalina.sh 2010-08-09 13:06:38.000000000 +0200
@@ -164,12 +164,17 @@
# Add tomcat-juli.jar and bootstrap.jar to classpath
# tomcat-juli.jar can be over-ridden per instance
if [ ! -z "$CLASSPATH" ] ; then
- CLASSPATH="$CLASSPATH":
+ CLASSPATH="$CLASSPATH:"
fi
-if [ "$CATALINA_BASE" != "$CATALINA_HOME" ] && [ -r "$CATALINA_BASE/bin/tomcat-juli.jar" ] ; then
- CLASSPATH="$CLASSPATH""$CATALINA_BASE"/bin/tomcat-juli.jar:"$CATALINA_HOME"/bin/bootstrap.jar
-else
- CLASSPATH="$CLASSPATH""$CATALINA_HOME"/bin/bootstrap.jar
+
+CLASSPATH="$CLASSPATH""$CATALINA_HOME"/bin/bootstrap.jar
+
+if [ "$CATALINA_BASE" != "$CATALINA_HOME" ] && [ -r "$CATALINA_HOME/bin/tomcat-juli.jar" ] ; then
+ CLASSPATH="$CLASSPATH:$CATALINA_HOME/bin/tomcat-juli.jar"
+fi
+
+if [ -r "$CATALINA_HOME/lib/apache-jul-log4j-bridge.jar" -a -r "$CATALINA_HOME/lib/log4j-1.2.15.jar" ] ; then
+ CLASSPATH="$CLASSPATH:$CATALINA_HOME/lib/apache-jul-log4j-bridge.jar:$CATALINA_HOME/lib/log4j-1.2.15.jar:$CATALINA_HOME/lib"
fi
if [ -z "$CATALINA_OUT" ] ; then
* Override ''java.util.logging.manager'' property either via ''LOGGING_MANAGER'' or ''JAVA_OPTS'' (check your startup scripts and ''catalina.sh'' about how to do it correctly):
LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.logging.julbridge.JULBridgeLogManager"
* If you install Tomcat on SuSE from rpm, instead of fixing ''catalina.sh'' you need to fix ''/etc/init.d/tomcat6'' (or ''/usr/sbin/dtomcat6''):
--- /usr/bin/dtomcat6.orig 2011-02-22 23:20:16.000000000 +0100
+++ /usr/bin/dtomcat6 2011-12-12 10:29:12.000000000 +0100
@@ -24,6 +25,9 @@
fi
CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/bin/bootstrap.jar"
CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/bin/tomcat-juli.jar"
+CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/lib/apache-jul-log4j-bridge.jar"
+CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/lib/log4j-1.2.15.jar"
+CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/lib"
CLASSPATH="${CLASSPATH}:$(build-classpath commons-daemon 2>/dev/null)"
if [ "$1" = "start" ]; then
@@ -34,7 +38,7 @@
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \
-Djava.io.tmpdir="$CATALINA_TMPDIR" \
-Djava.util.logging.config.file="${CATALINA_BASE}/conf/logging.properties" \
- -Djava.util.logging.manager="org.apache.juli.ClassLoaderLogManager" \
+ -Djava.util.logging.manager="org.apache.logging.julbridge.JULBridgeLogManager" \
org.apache.catalina.startup.Bootstrap start \
>> ${CATALINA_BASE}/logs/catalina.out 2>&1 &
if [ ! -z "$CATALINA_PID" ]; then
Finally, checklist:
* ''/usr/share/tomcat6/bin'' contains:
* ''catalina.sh'' (//patched for classpath//)
* ''tomcat-juli.jar'' (//from [[http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.32/bin/extras/|extras]]//)
* ''/usr/share/tomcat6/lib'' contains:
* ''tomcat-juli-adapters.jar'' (//from [[http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.32/bin/extras/|extras]]//)
* ''log4j.properties'' (//newly created//)
* ''log4j-1.2.15.jar''
* ''apache-jul-log4j-bridge.jar''
* ''/etc/default/tomcat6'' is fixed for ''LOGGING_MANAGER''.
and you are ready to restart Tomcat and enjoy the result.
For slf4j logging, check [[github>grgrzybek/tomcat-slf4j-logback|here]].
=== Quick deployment of Web application ===
See [[habrahabr>126066|Быстрая разработка веб-приложений на Java]]:
* [[maven#how_can_i_run_embedded_web_container|Jetty Maven plugin]] / [[http://www.gradle.org/jetty_plugin.html|Jetty Gradle plugin]] / [[googlecode>p/run-jetty-run/|Run Jetty Run]]
* [[http://www.eclipsetotale.com/tomcatPlugin.html|Eclipse Tomcat Launcher plugin]] / [[http://www.eclipse.org/webtools/|Eclipse WTP]]
* [[http://www.springsource.com/developer/sts|Springsource tool suite]]
=== Tomcat/Jetty remote JMX monitoring of JVM state ===
See [[habrahabr>147008|Рецепт настройки удалённого мониторинга контейнеров Tomcat и Jetty штатными средствами JDK]].
=== Enabling HTTP/2 ===
Several resposes from ''mod_jk'' could not be multiplexed into one HTTP/2 stream, see [[stackoverflowa>35705569/267197|this post]]. To enable multiplexing JBoss 5.x / [[http://tomcat.apache.org/whichversion.html#Apache_Tomcat_9.x|Apache Tomcat 9]] is required. There could be [[stackoverflowa>48103841/267197|different options where to offload TLS]]:
* Decrypt traffic and re-encrypt it for backend (''%%ProxyPass "/path" "h2://jboss.server"%%'' + '''' inside TLS enabled '''' element).
* Decrypt traffic and send it plaintext to backend (''%%ProxyPass "/path" "h2c://jboss.server"%%'' + '''' inside '''' element).
See also:
* [[https://httpd.apache.org/docs/trunk/mod/mod_proxy_http2.html#examples|mod_proxy_http2 examples]]
* [[https://tomcat.apache.org/tomcat-9.0-doc/config/http2.html|HTTP2 Upgrade Protocol]]
{{tag>Tomcat Jetty LDAP SPNEGO NTLM Kerberos JIRA Confluence Spring UTF}}