ClickStack - Application Containers » Tomcat7 ClickStack

Tomcat7 ClickStack

Last modified by Cyrille Le Clerc on 2014/04/15 13:15

The Tomcat7 ClickStack allows you to run your web application in a Tomcat 7 container.

How to deploy a web application on a Tomcat7 ClickStack

You can deploy your web application on the tomcat7 stack using the CloudBees SDK "app:deploy" command.

bees app:deploy -a myapp -t tomcat7 path/to/my/app.war
  • "-a myapp": name of the CloudBees account and of the application. The application will be accessible on the URL http://myapp.myaccount.cloudbees.net/
  • "-t tomcat7": identifier of the tomcat7 clickstack
  • "path/to/my/app.war": path to the war file.

You only need to set the "-R", "-t" and "-P" settings once - they will be remembered for subsequent deploys.

Binding a database to Tomcat 7

Binding a database to be used as a Tomcat datasource is very easy!

Simply use the SDK to create and bind a database as follows:

bees db:create MY_DB
bees app:bind -a MY_APP -db MY_DB -as mydb

You can now use in your application the "java:comp/env/jdbc/mydb" JNDI DataSource or access the System properties DATABASE_URL_MYDB, DATABASE_USERNAME_MYDB and DATABASE_PASSWORD_MYDB .

Code sample

Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/mydb");
Connection conn = ds.getConnection();
ResultSet rst = stmt.executeQuery("select 1");
while (rst.next()) {
    out.print("resultset result: " + rst.getString(1));
}
rst.close();
stmt.close();
conn.close();

Tomcat DataSource

The Tomcat7 Clickstack uses by default the  Tomcat JDBC Connection Pool with the following settings:

  • factory: 'org.apache.tomcat.jdbc.pool.DataSourceFactory'
  • url: 'jdbc:$DATABASE_URL_MYDB'
  • username: '$DATABASE_USERNAME_MYDB'
  • password: '$DATABASE_PASSWORD_MYDB'
  • maxActive: '20'
  • maxIdle: '10'
  • minIdle: '1'
  • testOnBorrow: 'true'
  • testWhileIdle: 'true'
  • validationInterval: '5000'
  • validationQuery: 'select 1'

Customising the DataSource

You can also specify any configuration attribute of Tomcat JDBC Connection Pool (defaultAutoCommit, fairQueue, maxAge, ...) as documented here.

Sample to limit maxActive to 10 connections:
bees app:bind -a MY_APP -db MY_DB -as mydb maxActive=10

Note: 

  • To change configuration settings, please unbind your database then rebind it with the needed attributes and finally restart your application.
  • Reducing maxActive to 10 connections can be useful when using a cluster of 2 Tomcat instances connecting to a CloudBees MySQL database that is limited to 20 connections max.

Using the old Apache Commons DBCP implementation

To use the old Apache Commons DBCP, instead of Tomcat JDBC Connection Pool you just have to specify factory=org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory during the binding of the database.

bees app:bind -a MY_APP -db MY_DB -as mydb factory=org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory

To change your configuration from DBCP to Tomcat JDBC Connection Pool, please unbind your database then rebind it with the factory attribute and finally restart your application.

Security

Private Application

The Private Application feature allows you to limit the access of your application with a secret based authentication mechanism deployed in front of your application.
Authentication can be done with a web form, with a basic authentication, with a http header or with a http parameter.

Sample to enable Private Application feature:
bees config:set -a myapp -R privateApp.secretKey=this_is_a_very_strong_secret_key
bees app:restart -a myapp

Sample to disable the Private Application feature:
bees config:unset -a myapp -R privateApp.secretKey
bees app:restart -a myapp

Private Application configuration parameter:

  • privateApp.secretKey: the secret key used to authenticate users. WARNING: this secret key must be strong to not be guessed! Mandatory
  • privateApp.authenticationEntryPointName: type of authentication (FORM_AUTH, BASIC_AUTH, HTTP_PARAM_AUTH or HTTP_HEADER_AUTH)
  • privateApp.authenticationParameterName: name of the HTTP parameter used to pass the secret key when using HTTP_PARAM_AUTH. Optional, default __cb_auth.
  • privateApp.authenticationHeaderName: name of the HTTP header to pass the secret key when using HTTP_HEADER_AUTH. Optional, default x-cb-auth.
  • privateApp.authenticationUri: URI used to submit the authentication form when using FORM_AUTH. Optional, default /__cb_auth.
  • privateApp.authenticationCookieName: name of the HTTP cookie in which is persisted the successful authentication. Optional, default __cb_auth.
  • privateApp.enabled: enable/disable flag. Optional, default true
  • privateApp.realmName: name of the realm used in authentication messages. Optional, default CloudBees
  • privateApp.ignoredUriRegexp: regexp of URIs to ignore when checking for authentication. Optional, default "/favicon\.ico"

Notes:

  • For BASIC_AUTH authentication, the password must match the configured secret key and the username is ignored.

IP Address Filtering

The IP Address Filtering feature allows you restrict to your application to users coming from a giving set of ip addresses. 

The typical use case is an Intranet Application that would restrict access with

  • SSL
  • IP Filtering: the incoming IP address must be one of the public IP addresses of the company's office
  • Authentication provided by the application

Sample to enable Private Application feature (sample with the "90.152.66.18"):

Command

$ bees config:set -a myapp -R remoteAddress.allow=90\\.152\\.66\\.18

Result

Application config parameters for cyrille-leclerc/ip-filtering-tcat7: saved

Runtime Parameters:
  remoteAddress.allow=90\.152\.66\.18
bees app:restart -f -a myapp

WARNING: The '\' chars in remoteAddress.allow and remoteAddress.deny MUST be escaped with '\' when using CloudBees CLI.

Remote Address Valve configuration parameter:

  • remoteAddress.allow: A regular expression (using java.util.regex) that the remote client's IP address is compared to. If this attribute is specified, the remote address MUST match for this request to be accepted. If this attribute is not specified, all requests will be accepted UNLESS the remote address matches a  remoteAddress.deny pattern. Mandatory
  • remoteAddress.deny: A regular expression (using java.util.regex) that the remote client's IP address is compared to. If this attribute is specified, the remote address MUST NOT match for this request to be accepted. If this attribute is not specified, request acceptance is governed solely by the remoteAddress.allow attribute.
  • remoteAddress.denyStatus: HTTP response status code that is used when rejecting denied request. The default value is 403. For example, it can be set to the value 404.

Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy

Change the JVM to use java7-jce_ustrength:

bees config:set -a myapp -R java_version=java7-jce_ustrength

Customising the JVM (Java 8 ...)

You can provide your own JVM or use a JVM provided by CloudBees on the repo http://cb-s3-dist.s3.amazonaws.com/ specifying a URL for the java_version configuration parameter.

Sample:

bees config:set -a myapp -R java_version=https://cb-s3-dist.s3.amazonaws.com/java/oracle/jdk-8-linux-x64.tar.gz

Pre-requisites on the provided JVM:

  • The url must use http://  or https://  and preferably be an Amazon S3 bucket located in the same region as your deployed server
  • The archive must be a ".zip", a ".tgz" or a ".tar.gz"
  • The JAVA_HOME must be the root of the expanded archive or there must be just one first level dir in the archive and that first level dir is the JAVA_HOME

Tomcat HTTP Connector Tuning

All the parameters of the Tomcat HTTP connector are configurable using the command bees config:set -a myapp -R tomcat.connector.MY_PARAM=MY_VALUE.

Where MY_PARAM is a valid HTTP connector configuration parameter as described in Tomcat Reference - The HTTP Connector.

To unset the configuration parameter, run the command bees config:unset -a myapp tomcat.connector.MY_PARAM.

Enabling HTTP Compression (gzip / gzip)

Tomcat supports HTTP/1.1 GZIP compression. The reference documentation is available here, by default, it only applies to text/html,text/xml,text/plain.

To enable HTTP compression, execute once the command:

bees config:set -a myapp -R tomcat.connector.compression=on

Changing the number of HTTP Threads (default is 200)

To change the number of HTTP threads, execute once the command (sample with 300 threads):

bees config:set -a myapp -R tomcat.connector.maxThreads=300

Changing the encoding of the request (default is UTF-8)

To change the URIEncoding, execute once the command (sample with "ISO-8859-1"):

bees config:set -a myapp -R tomcat.connector.URIEncoding=ISO-8859-1

Customising Tomcat server.xml

The Tomcat7 stack includes a pre-configured server.xml file that is used by default when you deploy an application.  If you need to customize the settings in this file, you can override it with your own copy by including it in your deployed WAR file at the following path: /META-INF/server.xml

Note: If you provide a custom server.xml, you should use the default version as the base to make sure that the connector port is properly used to set the assigned listening port when the server starts.

A demo of Tomcat server.xml file overriding is available at Tomcat7 NIO Connector Clickstart.

Customizing the Keystore and TrustStore of the JVM

You can provide your custom keystore and/or truststore that will be used by the JVM at startup

  • Add the keystore and/or truststore to the war file under $WAR_HOME/META-INF/extra-files (e.g. $WAR_HOME/META-INF/extra-files/keystore and $WAR_HOME/META-INF/extra-files/truststore)
    • with Maven war projects, the keystore and truststore must be stored in src/main/webapp/META-INF/extra-files/
    • It is usually a good practice to recopy the keystore provided by the JVM and to add the custom certificates to this copy
      cp $JAVA_HOME/jre/lib/security/cacerts $my_app_dir/src/main/webapp/META-INF/extra-files/keystore
      cp $JAVA_HOME/jre/lib/security/cacerts $my_app_dir/src/main/webapp/META-INF/extra-files/truststore
  • Declare the following
    • Linux (escape the $ char)
      bees config:set -a myapp -R JAVA_OPTS="-Djavax.net.ssl.keyStore=\$app_extra_files/keystore -Djavax.net.ssl.trustStore=\$app_extra_files/truststore"
      bees config:set -a myapp -P javax.net.ssl.keyStorePassword=changeit
      bees config:set -a myapp -P javax.net.ssl.trustStorePassword=changeit
    • Windows (no need to escape the $ char)
      bees config:set -a myapp -R JAVA_OPTS="-Djavax.net.ssl.keyStore=$app_extra_files/keystore -Djavax.net.ssl.trustStore=$app_extra_files/truststore"
      bees config:set -a myapp -P javax.net.ssl.keyStorePassword=changeit
      bees config:set -a myapp -P javax.net.ssl.trustStorePassword=changeit
  • For troubleshooting you can enable SSL logs
    bees config:set -a myapp -P javax.net.debug=all

Troubleshooting Tools

JMX Invoker

CloudBees JMX Invoker is a Bees SDK control script to execute arbitrary JMX commands on a running RUN@cloud instance.

Typical use cases cover

  • enabling/disabling logs changing a logger level at runtime
  • troubleshooting application checking status of components (dataSource.numActive, ...)
  • using JMX to implement the feature toggle pattern

Available JMX commands

  • list MBeans
  • describe MBeans to discover the available attributes and operations
  • read or write a MBean attribute
  • invoke an MBean operation

All the details about the CloudBees JMX Invoker are available at RUN@cloud » CloudBees JMX Invoker (syntax, samples, ...).

Other Troubleshooting tools (jstack, jstat, du)

jstack

bees app:invoke -a myapp -cs jstack

Generates a jstack threadump.

jstat

bees app:invoke -a myapp -cs jstat

Generates a jstat of 3 samples separated by 5 secs each.

du

bees app:invoke -a myapp -cs du

Generates a du -h -d 4.

How to add libraries to Tomcat server classpath

It is sometimes useful to add libraries directly to Tomcat server classpath (load time weaving jar, jdbc drivers, ...).

To do so, just add them to the META-INF/lib/ folder of your webapp.

Please note that the mysql jar is automatically added to your container classpath when you bind a MySQL database to your application with bees app:bind -db ... -a ....

A demo including Maven pom.xml configuration is available at: https://github.com/CloudBees-community/spring-load-time-weaving-clickstart.

Application Session Clustering

More details at RUN@cloud » Application Session Stores

Tuning application session clustering for performances (expert configuration)

The main idea of performance tuning for the clustering of sessions is to ensure that sticky sessions are enabled and thus remove session locking and use async replication of the sessions.

# Enable sticky sessions on the router
bees app:proxy:update stickySession=true -a MY_APP

# Update session clustering configuration
bees app:unbind -a MY_APP MY_SESSION_STORE
bees app:bind -a MY_APP -r MY_SESSION_STORE sticky=true sessionBackupAsync=true
bees app:restart -a MY_APP

Where MY_APP is the name of the application to update and MY_SESSION_STORE is the name of the session store. The name of the session store can be retrieved in the web console.

Customizing application session clustering (expert configuration)

Application session clustering for the Tomcat ClickStack relies on the memcached-session-manager.

WARNING: customizing application session clustering requires expert skills in memcached-session-manager.

The customizable parameters are described in memcached-session-manager > Setup and Configuration. Key configuration parameters:

  • transcoderFactoryClass: default value is "de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory". It is also possible to use the "de.javakaffee.web.msm.JavaSerializationTranscoderFactory".
  • customConverter: coma separated list of converters. Default value is "null". If you store Hibernate collections in the session, declare de.javakaffee.web.msm.serializer.kryo.HibernateCollectionsSerializerFactory. If you store Spring Security user, declare de.javakaffee.web.msm.serializer.kryo.SpringSecurityUserRegistration. If you store Grails FlashMap data, declare de.javakaffee.web.msm.serializer.kryo.GrailsFlashScopeRegistration
  • requestUriIgnorePattern: regular expression, default ".*\.(ico|png|gif|jpg|css|js)$"
  • sessionBackupAsync: default "true"

Samples: 

bees app:bind -a MY_APP -r MY_SESSION_STORE transcoderFactoryClass=de.javakaffee.web.msm.JavaSerializationTranscoderFactory
bees app:bind -a MY_APP -r MY_SESSION_STORE customConverter=de.javakaffee.web.msm.serializer.kryo.HibernateCollectionsSerializerFactory

To update the configuration parameters of an existing session store binding, please unbind and rebind the session store. 

Exporting Access Logs to PaperTrail

To export your access logs to PaperTrail, bind your application to PaperTrail and execute the following bees SDK command: 

bees config:set -a myapp -RaccessLog.syslog=true
  • The access logs format is by default "combined", it can be configured with "bees config:set -a myapp -R accessLog.pattern=combined|common|<custom>" where <custom> is defined following the syntax defined in Tomcat's AccessLogValve
  • In papertrail, the access logs will be attached to the same app (www in the screenshot below) but with a different server identifier ("access_log" instead of the ec2 identifier "i-xxx")

tomcat7-accesslogs-papertrail.png
Tomcat 7 ClickStack Access Logs in PaperTrail

Notes

Note - 2014/02/26: Potential regression restarting apps due to an upgrade to Tomcat 7.0.52

Tomcat 7.0.52 comes with critical security fixes and has been deployed on the CloudBees Tomcat 7 ClickStack.

Some applications will face regressions using tomcat 7.0.52 such as IllegalStateException: ClassLoader [org.apache.catalina.loader.WebappClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method (see SPR-11446: "Load Time Weaving not working after upgrading Tomcat from 7.0.50 to 7.0.52").

If you face an issue running with the latest version of Tomcat 7 ClickStack and Tomcat 7.0.52, you can continue to use Tomcat 7.0.50 running the following Bees SDK command: 

bees config:set -a myapp -RPLUGIN.SRC.tomcat7=http://s3.amazonaws.com/cloudbees-clickstack/core/tomcat-clickstack-7-1.0.10.zip
bees app:restart -a myapp

To remove this specific configuration and use the latest version of the Tomcat 7 ClickStack, please run "bees config:unset -a myapp PLUGIN.SRC.tomcat7".

To fix the Spring exception IllegalStateException: ClassLoader [org.apache.catalina.loader.WebappClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method, please declare a o.s.i.c.t.TomcatInstrumentableClassLoader as described in Using AspectJ Load Time Weaving for Spring Framework on CloudBees Tomcat 7.

To get assistance for this upgrade, please open a support ticket if you are a paying customer or post your request to users@cloudbees.com.

Release Notes

See https://github.com/CloudBees-community/tomcat-clickstack/releases

Tags:
Created by Cyrille Le Clerc on 2013/04/11 15:08