Software Requirements
For Sophora web applications, the minimum software requirements are:
- Java 11
- Apache Http Server 2.4
- Apache Tomcat 9
Notes on Tomcat 9
Tomcat 9 creates files with a restricted set of permissions. This is especially relevant for the files in the cache directory. These files should be read by the apache process and thus, should be readable by all users. Otherwise the apache process can’t read the files in the cache directory and all requests are served dynamically by the tomcat.
To fix this problem, the umask for the Tomcat must be changed. This is done by an environment variable:
export UMASK=0002
Apache Webserver Configuration
The webserver is installed in the following directory: install-path/apps/apache2
The httpd.conf
file of the webserver contains the hereafter listed Sophora-specific entries:
### sophora configuration
JkWorkersFile "conf/workers.properties"
JkLogFile "logs/mod_jk.log"
JkLogLevel error
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkOptions +ForwardKeySize +ForwardURICompat +ForwardDirectories
JkRequestLogFormat "%w %V %T"
LoadModule sophora_module modules/mod_sophora.so
# # VirtualHosts
Include /cms/ts/webapps/ts-preprod-live/conf/ts_httpd.conf
Include /cms/ts/webapps/ts-prod-live/conf/ts_httpd.conf
Connection between Apache and Tomcat
To connect the Tomcat with an Apache webserver it is important to set the sophora.delivery.render.isMounted
property in the corresponding context to true
. Additionally, the DocumentRoot from the Apache's configuration (see below) has to equal the sophora.delivery.cache.directory
of the context.
Example
Excerpt from sophora.properties
:
sophora.delivery.render.isMounted=true
sophora.delivery.cache.enabled=true
sophora.delivery.cache.directory=/cms/webapps/example-prod-live/cache/htdocs/example
Excerpt from Apache virtual host
config:
<VirtualHost www.example.com:80>
...
DocumentRoot /cms/webapps/example-prod-live/cache/htdocs/example
...
We recommend using mod_proxy
to manage communication between Apache and Tomcat. In comparison to mod_jk and mod_ajp_proxy, mod_proxy
has yielded the best results stability and performance.
mod_jk
- problem:
mod_jk
is often unavailable for the Apache and need to be translated. Older versions sometimes cause trouble. - problem: Apache 1 prevented the execution of the SSI filter within the webserver after the creation of a file in the Tomcat. In Apache 2 this works.
- problem: If the Tomcat generates a PHP page, the Apache only delivers plain PHP code. The code isn't interpreted until a second call (at that point the file is in the docroot directory and the Tomcat isn't required).
mod_proxy
The mod_proxy
configuration is similar to mod_jk
solution. However, the mod_proxy
is more standard like and easier to use. But the problems remain the same: SSI is only supported by the Apache 2 and PHP isn't interpreted in the first place.
Here is an exemplary Apache configuration with this context: sophora.delivery.cache.directory=/cms/webapps/example-prod-live/cache
<VirtualHost www.example.com:80>
UseCanonicalName On
DocumentRoot /cms/webapps/example-prod-live/cache/htdocs/example
LogLevel warn
ProxyPreserveHost On
AddOutputFilter INCLUDES .html .php .jsp .xml
<Location /example-prod-live>
SetOutputFilter INCLUDES
</Location>
AddCharset UTF-8 .html
ProxyRequests Off
ProxyMaxForwards 50
ProxyErrorOverride Off
ProxyPass /example-prod-live/ http://localhost:8080/example-prod-live/
ProxyPassReverse /example-prod-live/ http://localhost:8080/example-prod-live/
# Die Verbindung per AJP macht oft Probleme
# ProxyPass /example-prod-live/ ajp://localhost:8009/example-prod-live/
# ProxyPassReverse /example-prod-live/ ajp://localhost:8009/example-prod-live/
RewriteEngine on
RewriteLog /cms/webapps/example-prod-live/logs/example_rewrite_log
RewriteLogLevel 0
<Directory />
Options Includes ExecCGI FollowSymLinks
</Directory>
# Add missing trailing slash for directories
RewriteCond %{DOCUMENT_ROOT}/%{SCRIPT_FILENAME} -d
RewriteRule ^(.+[Sophora Delivery^/])$ $1/ [R,L]
# Redirect to homepage
RewriteCond %{SCRIPT_FILENAME} ^/$
RewriteRule ^/$ /index.html
# Replacement for DirectoryIndex
RewriteRule ^(.*)/$ $1/index.html
# Use tomcat for dynamic content
RewriteCond %{SCRIPT_FILENAME} !^/example-prod-live/(.*)$
RewriteCond %{SCRIPT_FILENAME} ^/.*\.jsp$
RewriteRule ^/(.*)$ /example-prod-live/example/$1 [PT]
# If we reach this point it must be cacheable content
RewriteCond %{DOCUMENT_ROOT}%{SCRIPT_FILENAME} !-f
RewriteRule ^/(.*)$ /example-prod-live/example/$1 [PT]
</VirtualHost>
Tomcat Configuration
The Tomcat is located at install-path/apps/tomcat
. It needs to be started by the user "sophora" using the command ./startup.sh
in the directory install-path/apps/tomcat/bin
. In the same directory you can stop the Tomcat using the command ./shutdown.sh
. Within all servers the Tomcat is configured to listen to port 9000. The configuration of the individual context is located in the install-path/apps/tomcat/conf/Catalina/localhost
directory.
The context-xml file for each webapp (tomcat/conf/Catalina/localhost/<contextname>.xml)
must contain two settings:
- The parameter
localConfigDirectory
: path of the directory, where the localsophora.properties
file of the webapp is located. - The environment variable
logPath: path
of the directory where the logs should be written.
Example context-xml
:
<?xml version='1.0' encoding='utf-8'?>
<Context docBase="/cms/ndr/webapps/ndr-prod-live/webapp" path="/ndr-prod-live" reloadable="false" override="true">
<Parameter name="localConfigDirectory" value="/cms/ndr/webapps/ndr-prod-live/conf/"/>
<Environment name="logPath" value="/cms/ndr/webapps/ndr-prod-live/logs" type="java.lang.String"/>
</Context>
To avoid excessive memory ussage the tag pool size should be set to zero in the tomcat web.xml
:
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>tagpoolMaxSize</param-name>
<param-value>0</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
Configuration of the Sophora Delivery Web Application(s)
Web applications are located in the server's install-path/webapps
directory. There you'll find a subdirectory for every context. For example:
install-path/webapps/ts-prod-live
Every context contains the following subdirectories:
cache
conf
logs
webapp
The webapplication will be deployed in the webapp
subfolder. Jenkins is recommended for the deployment process. You can find more information about Jenkins in the section Deployment.
The configuration files are located in the conf directory. There you'll find the central configuration file sophora.properties
for the web appliction as well as configuration files for the virtual hosts.
Exemplary sophora.properties
file:
sophora.serviceUrl=rmi://www.sophora-cms.com:1199/ContentManager
sophora.delivery.client.username=webadmin
sophora.delivery.client.password=admin
sophora.delivery.render.isMounted=false
sophora.delivery.render.isLive=false
sophora.delivery.cache.enabled=false
sophora.delivery.cache.directory=C:/repos/sophora_web/cache
sophora.delivery.cache.pregeneration.enabled=false
sophora.delivery.cache.pregeneration.maxAccessTimeInterval=180
sophora.delivery.cache.pregeneration.numberOfThreads=1
sophora.delivery.cache.pregeneration.httpTimeout=240
sophora.delivery.url=http://localhost:8080/sophora-ts
sophora.delivery.externalUrl=http://www.sophora-cms.com:8080/sophora-ts
sophora.delivery.cache.groups=group1
log4j.logger.com.subshell.sophora.delivery.cache=INFO
log4j.rootLogger=WARN,stdout,logfile
An overview of all configuration parameters can be found in section Configuration Parameters.
Local Configuration Directory
The local configuration directory contains a sophora.properties
file that overwrites the settings as defined in the web project's configuration file src/web/WEB_INF/sites/sophora.properties
. Thus, for properties that exist in both files, the values from the local one replace those from the global (project wide) configuration file. During development, it might be useful to disable the caching locally or to change the server connection details without changing the entire project configuration.
The delivery requires a sophora.properties
file within the local configuration folder. If this file is empty, all properties are retained from the global configuration file. If the local sophora.properties
files cannot be detected, the delivery startup fails. In the following example the server connection details are overwritten:
local_sophora.properties
#sophora.serviceUrl=http://cms.server.com:1199
sophora.serviceUrl=localhost:1199
sophora.delivery.client.username=admin
sophora.delivery.client.password=adminPassword
Running the web application from an IDE
When running the webapp from Eclipse (on an embedded Tomcat), The path to the local configuration has to be specified within the src/web/META-INF/context.xml
as follows:
context.xml
<?xml version='1.0' encoding='utf-8'?>
<Context>
<Parameter name="localConfigDirectory" value="c:\sophora\webapp\localConfigurationDir"/>
</Context>
Configuring Websites within the Web Project
- For each website the directory
src/web/WEB-INF/sites
has to contain a file<sitename>.properties
. As with thesophora.properties
, the properties given in the<sitename>.properties
files can be overwritten in the correspondent files that are located in the local configuration directories. Templates then apply the properties dependent on the website the user is currently viewing. - Also, the directory
src/web/WEB-INF/templates/<sitename>
has to contain a filetemplates.xml
. Within this file, it is determined which JSP templates should be used when a certain document type is requested. For more information see the page templates.xml.
Configuration Parameters
The following table contains all possible configuration parameters, a brief description and, if non-trivial, an exemplary value.
Property | Description + Example |
---|---|
sophora.serviceUrl | Server connection, e.g. rmi://www.sophora-cms.com:1199/ContentManager |
sophora.delivery.client.username | Username for server login |
sophora.delivery.client.password | Password for server login |
sophora.delivery.client.accesstoken | May be used as an alternativ authentication method. This property is belongs to the AddOn Sophora Cloud Delivery. |
sophora.delivery.client.sessionless | If the delivery communicates with multiple staging server behind a loadbalancer, this option should be set to true. This can only be used, if either http or https is used (default is false). This property is belongs to the AddOn Sophora Cloud Delivery. |
sophora.delivery.url | URL of this delivery. Is also used by the pre-generation. Example: http://localhost:8080/demo |
sophora.delivery.externalUrl | External URL of the delivery. This is the URL which other components (Staging Servers and other web applications) use to communicate with the delivery. It is used for cache flushes via the cache servlet and for URL generation via the URL4Id servlet. Example: http://delivery1.domain.com:8080/demo |
sophora.delivery.cache.groups | Via this property multiple delivery can form a group in which external cache flushes are propagated by the cache servlet. |
sophora.delivery.cache.db | Which database should be used for caching? Possible values: derby, derbyng (since version 1.32.4 and 1.33.1), asyncderby (version 1.32.4 and 1.33.1). For the versions after 1.32.4 and 1.33.1 consider the property sophora.delivery.cache.db.async. (Default: derby) |
sophora.delivery.cache.db.async | Defines whether the database should be updated asynchronously after a request (default true). Since delivery version 1.32.5 and 1.33.2. See the section Asynchronal Update of the Cache Database for further information. |
sophora.delivery.cache.derby.optimizing.enabled | Whether or not the optimisation of the derby db cache should to be done (default is true). |
sophora.delivery.cache.derby.optimizing.cron | How often to run the derby db cache optimisation (default: 0 0 3 1/1 * ? * ) |
sophora.delivery.cache.cleanup.enabled | Whether or not the cleanup of the db cache should to be done (default is false). |
sophora.delivery.cache.cleanup.cron | How often to run the db cache cleanup (default: 0 0 1 1/1 * ? * ) |
sophora.delivery.cache.filecleanup.enabled | Enables the clean up of the file system cache. Removes all cached file which are nor registered in the database. (default false) |
sophora.delivery.cache.filecleanup.cron | Cron expression for the file system clean up (default: 0 30 0 1/1 * ? * ) |
sophora.delivery.cache.removeFromCacheRegistry | Remove the cache entries from cache db for a removed file (default: true). If set to false the cache db cleanup job should be enabled. |
sophora.delivery.cache.removalQueue | Type of removal queue: derbyRemovalQueue (Default), cachingDerbyRemovalQueue (faster derby implementation), memoryRemovalQueue (pure memory implementation; only recommended in combination with sophora.delivery.cache.removeFromCacheRegistry=false ) |
sophora.delivery.cache.removal.maxParallelGenerationsBeforeThrottle | Maximum number of concurrent cache generations before the removal queue worker is throttled (default 30) |
sophora.delivery.cache.enabled | Keep generated file in the cache (true/false )? |
sophora.delivery.cache.directory | Directory to save cached files and the cache database in (i.e. /cms/webapps/demosite/cache ) |
sophora.delivery.cache.threshold | Only cache fragments, whose generation time took longer than this threshold are cached. The value defines this threshold in milliseconds. This configuration parameter is used, to reduce the number of cached fragments. If a cache fragment generates very fast, the cache overhead might be more expensive than the generation of the cache fragment. The default value is 0, so that all requests are cached. Please consider also the other criteria, which defines whether a request is cached or not. Like the configuration parameter sophora.delivery.cache.enabled and the list of suffixes which are excluded from the caching. Static resources are cached even if there generate time is below the threshold. |
sophora.delivery.cache.trackFieldAccess | Whether or not field access will be tracked (default: true ). If tracking of field access is enabled only changes to fields that were relevant during the rendering of the html file of a document will force a cache invalidation. If it is disabled all changes of a document will force a cache invalidation of its html file. |
sophora.delivery.cache.event.password | Password that protects the cache servlet, see caching section for more information |
sophora.delivery.cache.requestTimeout | Timeout in minutes for cached requests. Default value is 10. When this values is set to 0 no timeout is active. |
sophora.delivery.cache.sophoraclient.cacheregistration.enabled | Defines whether or not documents which are accessed via the ISophoraClient during requests should be taken into account for the registration of dependent documents of the resulting cache fragment. The default value is false , so that only documents which were accessed via the sophora taglib or the ContentProvider are taken into account. The option is useful, to ensure an automatic cache invalidation even if the sophora taglib or the ContentProvider are not used to serve client requests. This may be the case when Spring Data Sophora is used. Values: true/false |
sophora.delivery.cache.ephemeralEntriesThresholdInSeconds | If set, all cache fragments with a life time below this amount of seconds will be treated as ephemeral. This implies a memory-only handling and reduces stress on your cache database. Only works together with the async cache db. See the article on caching for details. (Since 2.5.26) |
sophora.delivery.contentTypePropertyName | The name of the property which stores the content types, for example sophora:contentType |
sophora.delivery.render.isMounted | Does the Tomcat operate within an Apache webserver(true/false) ? |
sophora.delivery.forceSsiThroughTomcat | If set to true, the tomcat server will evaluate all SSIs regardless of whether it operates with an Apache webserver or not. Enable this option to fill the developer tool bar with metrics about caching and includes. Default is false. |
sophora.delivery.render.isLive | Is this a live delivery? If that's the case, time schedules and offline documents are regarded always according to the current request time. Otherwise not (due to preview). Values: true/false |
sophora.delivery.render.preview.includeOfflineDocuments | Show referenced documents in preview even if their document state is 'offline'. Values: true/false - Default: true |
sophora.delivery.render.defaultContentMapName | The name of the default content map that is set into the request (default: content) |
sophora.delivery.showDevToolbar | Corresponds the Sophora JSP tag "devToolbar". The developer toolbar will just be shown, if this property is set to true. (default: false) |
sophora.delivery.client.documentCacheOverflowToDisk | Defines whether documents should be persisted on disk by the document cache. Values: true/false - Default: false. Replaces the property sophora.delivery.client.documentCacheElementsOnDisk since version 1.38.0 The cached data is stored in sophora.delivery.cache.directory/documents . |
sophora.delivery.client.documentCacheElementsInMemory | Maximum number of documents that are kept in memory by the document cache. This property must not be set to an empty (or non-numeric) value. Otherwise the webapplication-context can't be created. Default is 5000 (This property replaces sophora.delivery.client.documentCacheSize ). The value 0 means that there is no limit. |
sophora.delivery.client.documentCacheStatistics | Activates cache statistics which can be read via JMX. (default: false) |
sophora.delivery.jmx.port | Used to communicate the JMX port to the Sophora Admin Dashboard. This option is useful when multiple deliveries are running on the same host. Note: The delivery will not manage this port. The application using the delivery is responsible for making JMX available for remote access. |
sophora.delivery.defaultNamespaces | Which namespaces should be filtered from the content map? Values as comma separated list, like for example sophora-content, sophora-extension |
sophora.delivery.nonOverridablePropertyNames | Comma separated list of properties that must not be overwritten with an empty value. |
sophora.delivery.ignoredSophoraIds.size | The size of the cache for the ignoreList (default: 1000) |
sophora.delivery.cache.remove.limit | Differentiation between the priorities of cache files that should be deleted or generated in the priority queue. You can enter as much values as you want to realise smaller priorisation steps. As an example, consider the following priorisations: 100, 1000, 10000. If less than 100 files are affected by an operation, these files will be processed with priority "3" (which is the highest). If 100 to 999 files are affected, they are categorised with priority "2". If 1000 to 9999 files are affected, they are assigned with priority "1". If the operation affects more than 9999 files, they will be processed with the lowest priority (priority "0"). (Default: 20,100,500,1000,10000,50000) |
sophora.delivery.cache.remove.dateFlush.limit | Priority for time scheduled flushes. You can enter a static value, such as "4", or you can set a relative priority by adding a plus ("+") or minus ("-") sign in front of a priority value, i.e. "+4". The relative priority is then added to the highest priority of the remove.limit property. By default, this flush priority is left blank so that the highest priority of the remove.limit property is adopted. |
sophora.delivery.cache.pregeneration.enabled | Enable pre-generation (true/false )? |
sophora.delivery.cache.pregeneration.urlProviderTemplate | JSP template for providing the URL used for the pregeneration of a sophora document, e.g. /site/system/pregenfilename.jsp?id= // This is needed only for generation of non-existing files. (see generateNonExistentFiles) Use the UUID of sophora documents as ID key here. |
sophora.delivery.cache.pregeneration.maxAccessTimeInterval | Access time of pre-generated files (in seconds, e.g. 600) |
sophora.delivery.cache.pregeneration.numberOfThreads | Number of threads for the pre-generation task |
sophora.delivery.cache.pregeneration.httpTimeout | Timeout for the request of the HTTP client of the pre-generation (in seconds, e.g. 30) |
sophora.delivery.cache.pregeneration.generateNonExistentFiles | Should a file be pre-generated if a document is published and the file does not exist in the cache, or if a cache entry is explicitly flushed by a tag or the cache servlet (true/false )? The file is determined through the JSP urlProviderTemplate (see above). Note: Pregeneration of SSIs and other references (images etc) is not supported. |
sophora.delivery.cache.pregeneration.boostAccessTimeInterval | Access time to boost priority for files to pregenerate (in seconds. Default: 86400) |
sophora.delivery.cache.pregeneration.boostPriority | Priority-Boost for file pregeneration. (Default: -1) |
sophora.delivery.cache.alive.logfile | Path to the file which records the time when the Sophora Server was connected lastly |
sophora.rmi.cache.registryPort | Port for the CacheExporter-RMI |
sophora.rmi.cache.servicePort | Port for the RMI service |
sophora.delivery.cache.resourceChangedFlushInterval | Interval size (in seconds) to check for changed resources, like JSP files (default 60sec) |
sophora.delivery.cache.flushDateFlushInterval | Interval size (in seconds) to check for date flushes (default 60sec) |
sophora.delivery.cache.flushPassword | Password of the flush template for external cache keys |
sophora.delivery.cache.replication.fileFilter | Files that match this regular expression should be moved to the cache. A possible value might be .*(.php) |
sophora.delivery.cache.replication.period | Periodicity of static files to be replicated into the cache directory (in milli seconds) |
sophora.delivery.cache.facade.numberOfThreads | Number of threads within the cache facade that may access the cache simultaneously |
sophora.delivery.cache.event.cleanupInterval | Interval size to remove out-dated entries from the event database of the cache (in milli seconds) |
sophora.delivery.cache.event.lifetimeMinutes | After how many minutes should an event be removed from the cache's event database? |
sophora.delivery.sendMailAsFormRegExp | Regular Expression for validation of email adresses: ^(.+)@(.{2,)\.(.{2,4})$}} |
sophora.delivery.ssi.queryStringVariableName | The variable name of the query string for the active SSI document (default: QUERY_STRING). |
sophora.delivery.templateSuffixes | A comma-seperated list containing template-suffixes to be used instead of .html. The first element has the highest priority. Default is jsp, jspx |
sophora.delivery.template.checkInterval | Interval to check the template.xml for changes (in seconds) |
sophora.delivery.urlCodec.validateUrlParams | Shall URLs with parameters get a check sum (true/false )? Default is false |
sophora.delivery.urlCodec.allowForeignSiteContent | In Sophora, any content is available within all URLs that contain an existing structure path. By default, this also holds for content from other sites. By setting this property to false , requesting content within a structure path that does not belong to the URL's site will result in a 404. Default: true |
sophora.delivery.urlCodec.name | Decide which urlCodec is used for delivery. Sophora only ships with the "defaultSophoraCodec", which is the default. |
sophora.delivery.locale | Which Locale should be use for the date format function in the ContentMap (default: de_DE) |
sophora.delivery.captcha.usedFormCheck | Also check the form ID in submitted forms (true/false )? Default is false |
sophora.delivery.site.YOUR_SITE_NAME.domain | The domain prefix for the generation of URLs. If the link is created for a site other than the current one, this prefix will be prepended. For example, http://www.site1.de or http://www.site2.de Must be configured in sophora.properties |
sophora.delivery.site.YOUR_SITE_NAME.urlPrefix | URL prefix for the URL generation. If the delivery runs in the "mounted" mode, this prefix will be prepended. Example: /welle1 or /welle2 Must be configured in sophora.properties |
sophora.delivery.structureNodeRedirect.responseCode | HTTP response status code for redirected requests. Default is 302. |
sophora.delivery.http.proxy.host | Hostname of the HTTP proxy which is used for HTTP requests between several deliveries. May only be used in combination with the sophora.delivery.http.proxy.port property. |
sophora.delivery.http.proxy.port | Port number of the HTTP proxy which is used for HTTP requests between several deliveries. May only be used in combination with the sophora.delivery.http.proxy.host property. |
sophora.delivery.http.proxy.user | Login name for HTTP proxy which is used for HTTP requests between several deliveries. (optional) |
sophora.delivery.http.proxy.password | Password for the HTTP proxy which is used for HTTP requests between several deliveries. (optional) |
sophora.delivery.logconfiguration.disabled | Disable the default configuration of log4j. Default is false |
sophora.delivery.client.connectRetries | Number of retries to connect to Sophora server before giving up. Default is 50. |
sophora.delivery.client.connectRetryInterval | Interval in seconds between retries to connect to Sophora server. Default is 20. |
sophora.delivery.documentType.extension.[NODE_TYPE_NAME] | A comma-separated list containing allowed url-suffixes for the given nodetype name. e.g.: sophora.delivery.documentType.extension.sophora-content-nt\:video=html,jsp,xml,json Only .html, .jsp, .xml and .json are allowed suffixes for requests to video documents. Please note that ':' in the fully qualified nodetype-name has to be escaped '\:' If you want to make a restriction for all nodetypes, the placeholder allNodeTypes can be used. This extensions are used for all node types. For node types with a specific configuration the allowed suffixes are added. That feature only work if delivery is configured as live delivery. |
sophora.delivery.solr.url | Which SolR-Server should be use. Default is: http://localhost:1196/solr (Since 2.1.16, 2.2.6, 2.3.0: should not be set because it is retrieved from the current Staging Server) |
sophora.delivery.solr.user | Username for the solr server. Default: solr (Since 2.1.16, 2.2.6, 2.3.0: should not be set because it is retrieved from the current Staging Server) |
sophora.delivery.solr.password | Password for the solr server. Default: solr (Since 2.1.16, 2.2.6, 2.3.0: should not be set because it is retrieved from the current Staging Server) |
sophora.delivery.solr.query.parameter.tz | The time zone as canonical id. Default: Europe/Berlin |
sophora.delivery.solr.socket.timeout | The socket timeout for connections to the solr server measured in milli seconds. Defaults to 3000 |
sophora.delivery.solr.connection.timeout | The timeout for connecting to the solr server measured in milli seconds. Defaults to 1000 |
sophora.delivery.solr.maxconnections | The number of parallel connections allowed through the deliveries Solr client. Defaults to 100 |
sophora.delivery.solrcloud.enabled | Enable SolrCloud support. If enabled, all solr search requests are targeted at SolrCloud. Defaults to false . |
sophora.delivery.solrcloud.zkHosts | List of Zookeeper hosts that are part of the SolrCloud cluster. |
sophora.delivery.solrcloud.username | Solr username if the SolrCloud Basic Authentication Plugin is enabled. |
sophora.delivery.solrcloud.password | Solr password if the SolrCloud Basic Authentication Plugin is enabled. |
sophora.delivery.solrcloud.connection.timeout | Solr connection timeout in ms. Defaults to 60000 . |
sophora.delivery.solrcloud.socker.timeout | Solr socket timeout in ms. Defaults to 600000 . |
sophora.client.dataDir | Defines a directory which may be used by the Sophora Client Api for persisting information like the available nodes in a cluster. The directory must be specified over an absolute path. This is only reasonable for a preview delivery. |
sophora.delivery.classReloading.active | Automatic reloading of model and function classes. Default: true |
sophora.delivery.classReloading.delaySeconds | Delay in seconds for automatic class reloading. Default: 10 |
sophora.delivery.spring.additionalBasePackages | A comma-separated list of Java package names which will additionally be considered for Spring component scanning when the Delivery is initialized. |
Filesystem Cache Folders
The subdirectory install-path/webapps/context/cache
contains
- a directory
db
and - a directory
removal
and - a link
htdocs -> ../../../htdocs/ts-prod-live
.
The directory db
is the location of the registry of the cache manager. The directory removal
contains the persistent data of the removal- as well as the preGenerating queue. The link htdocs
ensures that the HTML cache is located at a defined position within the directory structure but may be spotted elsewhere if necessary.
Configuring the Derby Cache DB
To deactivate the optimization of storage space within the Derby DB, you have to set the property sophora.delivery.cache.derby.optimizing.enabled
to false. The database optimization is executed once a day at 3am by default, but can be changed via the property sophora.delivery.cache.derby.optimizing.cron.
Logging
Log4J has been removed as the logging framework for the delivery, in favour of SLF4J. SLF4J is a logging facade, a backend has to be provided by the web-application. This allows any SLF4J-compliant logging framework to be used in the web-application, such as log4j or logback. We recommend using logback, because it supports automatic reloading of the configuration file and configuration via JMX.
A logging configuration and the .jars
of the logging backend must be provided by the web-application.
To configure logging using logback, a logback.xml
file has to be added to the web-application's classpath (e.g. under WEB_INF/classes). The following example shows a configuration that behaves similar to the log4j-configuration used in previous sophora releases:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">
<jmxConfigurator />
<insertFromJNDI env-entry-name="java:comp/env/logPath" as="LOGPATH" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%thread|%thread] %-5level %.40c:%L - %msg %n</pattern>
</encoder>
</appender>
<appender name="logfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${LOGPATH}/delivery.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOGPATH}/delivery.%d{yyyy-MM-dd}.log
</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>[%d{ISO8601}, %-5p] [%t|%t] %m%n</pattern>
</encoder>
</appender>
<appender name="cachefile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${LOGPATH}/cache.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOGPATH}/cache.%d{yyyy-MM-dd}.log
</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>[%d{ISO8601}] [%t|%t] %m%n</pattern>
</encoder>
</appender>
<appender name="errorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<File>${LOGPATH}/error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOGPATH}/error.%d{yyyy-MM-dd}.log
</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>[%d{ISO8601}, %-5p] [%t|%t] %.40c:%L: %m%n</pattern>
</encoder>
</appender>
<logger name="org.apache.commons.httpclient" level="ERROR" />
<logger name="com.subshell.sophora" level="WARN" />
<logger name="com.subshell.sophora.delivery.filter.BenchmarkFilter" level="INFO" />
<logger name="com.subshell.sophora.delivery.cache" level="INFO" additivity="false">
<appender-ref ref="cachefile" />
</logger>
<root level="WARN">
<appender-ref ref="logfile" />
<appender-ref ref="errorLog" />
</root>
</configuration>
Using this configuration, logback will write the logfiles:
- delivery.log
- cache.log
- error.log
in the [LOGPATH] directory. This should be the same place where the former log4j default-configuration placed the logfiles. This configuration uses LOGPATH
as a placeholder for the logs directory. So this configuration can be used for multiple installations.
To define the LOGPATH
variable, a java.lang.String
-resource has to be provided by the container. This resource can be added to the context in the container's context-configuration (e.g. context.xml
):
<?xml version='1.0' encoding='utf-8'?>
<Context>
...
<Environment name="logPath" value="/cms/portal/webapps/myportal/logs" type="java.lang.String"/>
...
</Context>
/cms/<portal>/apps/tomcat/conf/Catalina/localhost/<webappname>.xml.
The LOGPATH
variable can also be set in the application's web.xml
using the following definition. This is only recommended if the configuration via the context is insufficient or not possible for any reason.
web.xml
<env-entry>
<env-entry-name>logPath</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>/cms/portal/webapps/myportal/logs</env-entry-value>
</env-entry>
In addition, this directory contains - depending on the webserver's configuration - log files for each website:
<site>_access_log (e.g. ts_access_log)
<site>_error_log
<site>_rewrite_log
Finally the following .jars
have to be present in the web-application's classpath (WEB-INF/lib
):
- logback-classic-0.9.27.jar
- logback-core-0.9.27.jar
- slf4j-api-1.6.1.jar
If maven is used in the web-project the following dependency can be added to the pom:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>0.9.27</version>
<type>jar</type>
</dependency>
Recommended Configuration for productive environments
When setting up Sophora deliveries in production mode, you should have a look at our recommended settings for productive environments which contains a section on deliveries.
Filters
Each request is filtered by several servlet filters within the web application. Depending on the configuration filters may be omitted or disabled. The following sections describe how the filters can be defined in the web.xml
and by which parameters they can be configured. For more information about filters read the section The Sophora Filter Chain.
SiteEnvironmentSetupFilter
<filter>
<filter-name>SiteEnvironmentSetupFilter</filter-name>
<filter-class>
com.subshell.sophora.delivery.filter.SiteEnvironmentSetupFilter
</filter-class>
<init-param>
<param-name>resourcePathRegex</param-name>
<param-value>\.servlet</param-value>
</init-param>
</filter>
parameter | description | example |
---|---|---|
resourcePathRegex | A regular expression for path segments that should be handled by the tomcat as if they were directed to the system site even though there path is not directing to an existing site. The value \.servlet is the default if nothing is specified. It is not necessary to modify this for static resources (e.g. in common-folders) or content from web-jars since they are detected properly even without this configuration. | \.servlet |
SSIFilter
<filter>
<filter-name>SSIFilter</filter-name>
<filter-class>com.subshell.sophora.delivery.filter.SSIFilter</filter-class>
<init-param>
<param-name>contentTypePrefixes</param-name>
<param-value>text,application/xml,application/json</param-value>
</init-param>
</filter>
parameter | description | example |
---|---|---|
parameterEncoding | The encoding that should be used (by the URLUtil) to encode and decode the URL-Parameters | UTF-8 |
contentTypePrefixes | A comma-separated list of content-types that should be searched for SSI-commands. | text,application/xml,application/json |
httpHeader | A comma-separeted list of HTTP headers which should be copied from the initial request into the SSI requests. By default, no headers are copied. | X-Forwarded-For, User-Agent |
CacheFilter
<filter>
<filter-name>CacheFilter</filter-name>
<filter-class>
com.subshell.sophora.delivery.cache.filter.CacheFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>noCachingSuffixes</param-name>
<param-value>.servlet</param-value>
</init-param>
</filter>
parameter | description | example |
---|---|---|
encoding | The encoding that will be used by the cache filter for reading and writing cache fragments. | UTF-8 |
noCachingSuffixes | a comma separated list of suffixes that will be ignored by the CacheFilter. Requests with URLs ending with one of these suffixes will not lead to cache entries. | .servlet |
SophoraSessionFilter
<filter>
<filter-name>sophoraSessionFilter</filter-name>
<filter-class>
com.subshell.sophora.delivery.filter.SophoraSessionFilter
</filter-class>
</filter>
parameter | description | example |
---|---|---|
urlEncoding | The encoding that will be used to encode URLs. This encoding will also be used to generate SSIs. Default is UTF-8 | UTF-8 |
UrlDecoderFilter
<filter>
<filter-name>URLDecoderFilter</filter-name>
<filter-class>com.subshell.sophora.delivery.filter.URLDecoderFilter</filter-class>
<init-param>
<param-name>ignoreSuffixes</param-name>
<param-value>.servlet</param-value>
</init-param>
</filter>
parameter | description | example |
---|---|---|
ignoreSuffixes | A list of suffixes separated by semicolon that will be ignored by the URLDecoderFilter. This parameter is usually used for logical URLs like servlets that shouldn't be interpreted as a request to a static file nor to a sophora-document. | .servlet |
SetUtf8EncodingFilter
<filter>
<filter-name>sophoraUtf8EncodingFilter</filter-name>
<filter-class>
com.subshell.sophora.delivery.filter.SetUtf8EncodingFilter
</filter-class>
</filter>
BenchmarkFilter
<filter>
<filter-name>benchmarkFilter</filter-name>
<filter-class>
com.subshell.sophora.delivery.filter.BenchmarkFilter
</filter-class>
</filter>
MultipartFilter
<filter>
<filter-name>multipartFilter</filter-name>
<filter-class>com.subshell.sophora.delivery.filter.MultipartFilter</filter-class>
</filter>
parameter | description | example |
---|---|---|
maxFileSize | A numeric (long) value of the maximum size (in bytes) of a multipart request. | 1024 |
ExceptionLoggingFilter
<filter>
<filter-name>exceptionFilter</filter-name>
<filter-class>
com.subshell.sophora.commons.filter.ExceptionLoggingFilter
</filter-class>
</filter>
TrimFilter
<filter>
<filter-name>trimFilter</filter-name>
<filter-class>
com.subshell.sophora.commons.filter.TrimFilter
</filter-class>
</filter>
parameter | description | example |
---|---|---|
applicationSubtypes | A comma separated list of subtypes of the content-type application , for which the trim filter should be applied. | .xml |
applicationSubtypePrefixes | A comma separated list of subtype prefixes of the content-type application , for which the trim filter should be applied. | xml+,xhtml+,rss+,rdf+ |
ignoredTags | A comma seperated list of HTML-Tags in which lines should not be trimmed. | pre,textarea |
Sophora Initializer
The SophoraInitializer needs to be defined as a listener. It takes care of initializing the properties, templates and spring configurations.
<listener>
<listener-class>
com.subshell.sophora.delivery.configuration.SophoraInitializer
</listener-class>
</listener>
Servlets
To enable servlets, the suffix of the servlets must be excluded from certain Sophora filters.
To exclude certain suffixes from caching the cache filter needs to be configured by setting the parameter noCachingSuffixes
in the web.xml
like in the following example (the excluded suffix is ".servlet"):
<filter>
<filter-name>CacheFilter</filter-name>
<filter-class>
com.subshell.sophora.delivery.cache.filter.CacheFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>noCachingSuffixes</param-name>
<param-value>.servlet</param-value>
</init-param>
</filter>
To ignore suffixes in the URLDecoderFilter the ignoreSuffixes
parameter has to be used:
<filter>
<filter-name>URLDecoderFilter</filter-name>
<filter-class>
com.subshell.sophora.delivery.filter.URLDecoderFilter
</filter-class>
<init-param>
<param-name>ignoreSuffixes</param-name>
<param-value>.servlet</param-value>
</init-param>
</filter>
Get the document uuid for a URL (idForUrl.servlet)
There are some configurations to do in delivery in order to provide the "Open document by URL from clipboard" action within the main menu of the Deskclient. To configure the new idForUrl.servlet
execute the steps below:
1. Add to the web.xml
file:
<servlet>
<servlet-name>idForUrlServlet</servlet-name>
<servlet-class>com.subshell.sophora.delivery.servlet.IdForUrlServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>idForUrlServlet</servlet-name>
<url-pattern>/system/servlet/idForUrl.servlet</url-pattern>
</servlet-mapping>
1. Finally, the template for the preview (preview.jsp
) needs to evaluate the new parameter idForUrl
, and possibly forward to the servlet:
<%@ page session="false" pageEncoding="utf-8" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib tagdir="/WEB-INF/tags/sophora-commons" prefix="sc"%>
<%@ taglib uri="http://www.subshell.com/sophora/jsp" prefix="sophora" %>
<c:choose>
<c:when test="${param.idForUrl eq 1}">
<c:set var="redirectUrl" >/system/servlet/idForUrl.servlet?url=${param.url}</c:set>
<c:import url="${redirectUrl}" />
</c:when>
<c:otherwise>
<c:choose>
<c:when test="${param.print eq 1}">
<sophora:map sophoraid="${param.sophoraid}" doprint="${param.doprint}" admin="${param.admin}" var="params" />
<sophora:staticUrl path="/system/print.jsp" params="${params}" var="redirectUrl"/>
</c:when>
<c:when test="${!empty param.path}">
<sophora:url structureNodeUuid="${param.path}" var="redirectUrl" />
</c:when>
<c:otherwise>
<sc:createLink sophoraId="${param.sophoraid}" urlOnly="true" var="redirectUrl" />
</c:otherwise>
</c:choose>
<?xml version="1.0" encoding="UTF-8" ?>
<html>
<head>
<c:if test="${!empty redirectUrl}">
<meta http-equiv="refresh" content="0; URL=${redirectUrl}">
</c:if>
</head>
<body>
<c:if test="${empty redirectUrl}">
<b>Es wird kein Inhalt für dieses Dokument ausgespielt!</b>
</c:if>
</body>
</html>
</c:otherwise>
</c:choose>
To test whether the configuration is successful, you can call the preview.jsp with a queryString ?idForUrl=1&url='AnyPreviewUrl'
. The result of that request should be the UUID of the document shown in 'AnyPreviewUrl'.
Error-Sites
To configure error sites which will be rendered by the tomcat, they have to be configured in the DeskClient first. Within the property labeled 404-Error-Documents (sophora:notFoundErrorDocument
) on the configuration tab of a structure node, you can define error documents which will be delivered when a document is not found under the configured structure node. By default, this property inherits its value from parent structure nodes. The resulting site will have the status code 404 (Not Found).
Then, some additional configuration is needed:
ProxyErrorOverride
in the apache configuration has to be set tooff
, so the tomcat can deliver its own error sites.- In the web.xml you have to define jsp files which will be delivered as the default error page if there is no error document configured for an 404 request.
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/403.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
- The jsp files have to be placed directly under the webapp directory and have the following content:
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="contextPath" value="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}" />
<c:import url="${contextPath}/site/404-error100.html"/>
- The hostname, port and context path are set automatically. In this example a request resulting in a 404 error will show the sophora document 404-error100. The same has to be done for 403 and 500 error documents.
Deployment
The delivery webapplication is usually built and assembled by maven
and managed over SVN
or any other source code management system. The following section describes how Jenkins can be used to automatically checkout, build and deploy webapplications based on the sophora delivery infrastructure.
Jenkins
Jenkins is a java webapplication that monitors executions of jobs, such as building or deployning a software project. Jenkins integrates easily with SVN
and Maven
so that both technologies can be embedded in the deployment process. While using Jenkins it's possible to trigger deployment jobs either manually or based on events like a commit into the SVN. Each job can be configured and monitored by the Jenkins UI. For more information visit the Jenkis homepage.
The following section describes how to setup a simple deploy job for a delivery webapplication.
Deploy Job
- To setup a Job just open the Jenkins UI in a browser and click on
new Job
in the menu on the left. - Enter a descriptive name for the job and choose
Build a free-style software project
from the selection under the Job name textfield. - Click ok to save your selection an go on with the configuration.
- choose
Subversion
in the sectionSource Code Management
and enter theRepository URL
to the module you want to build and deploy - choose the event that starts the Job in the
Build Triggers
section - choose
Build after other projects are built
to make the Job dependent from other jobs e.g. test runs - choose
Poll SCM
if you want to start the job after a SVN commit (This might be useful for development and test environments) - leave the selection blank if you want to start the job manually
- add a build step
Invoke top-level Maven targets
in theBuild section
- after jenkins checked out or updated the project we want to build a war file that will be deployed on a servlet engine. So enter
clean package as Goals
- add another build step
Execute shell
- finally we have setup the deployment of the war file that has been build in the previous step. The following script copies the packaged war file to the delivery servers via rsync over ssh.
cd "${WORKSPACE}/target"
# Change into the directory of the assembled webapp.
WEBAPP_DIR="$(ls -1 *.war | sed -r -e 's|\.war$||')"
cd "${WEBAPP_DIR}"
# Copy webapp.
rsync --rsh "ssh -C" --delete -avz -c "." "sophora@${TARGET_HOST}:${TARGET_WEBAPP_DIR}"
where
TARGET_HOST
is the host where the application will be deployed andTARGET_WEBAPP_DIR
is the full qualified path to the context root of the webapplication
Mirroring
Static content is mirrored to several delivery machines by the mirror.sh script. This script mirrors a directory from the machine on which it is run to all Staging Servers that are connected to a Sophora Primary Server. The transfer is done via rsync
on SSH.
The following settings can be configured in the script's head:
Key | Description | Example |
---|---|---|
INTERVAL | Interval to mirror file changes to the Sophora Replica Servers (in seconds) | |
PID_FILE | Path on the filesystem where the script keeps its process ID | /var/run/sophora-mirror/sophora-mirror.pid |
REPLICATION_SLAVES_URL | "replicationSlaves" URL of the Sophora Primary Server which is used to identify all connected Sophora Staging Servers. | http://master.example.com:3696/replicationSlaves |
SOURCE_DIR | Path on the filesystem to the directory that should be mirrored | |
DEST_DIR | Path on the filesystem of the Sophora Replica Servers to the target directory. The directory is the same on every Staging Server. |
To start the script prompt ./mirror.sh.
If want to stop it, you can press CTRL+C or enter kill
at the process ID anytime. Before stopping the script completes the current mirroring job.