ServerConfigurationGuide

From RunaWFE
Jump to navigation Jump to search

WFE Server configuration guide

RunaWFE Free Workflow System (BPMS) Version 4.5.0

© 2003 - 2015, Consulting Group Runa

© 2015 - 2024, "Process Technologies" Ltd, this document is available under GNU FDL license. RunaWFE Free is an open source system distributed under a LGPL license (http://www.gnu.org/licenses/lgpl.html).

# Settings

System settings can be of 2 types: as key=value pairs (properties) and as lists (xml). Configuration file "resource" can be extended in same format by file "wfe.custom.resource". 1 resource can have only one extended file

Files wfe.custom.* can be located:

  • in application classpath
  • in any jar within wfe.custom directory

Note. Application classpath for Jboss4 includes:

  • conf directory
  • contents of any jar from deploy directory
  • contents of runawfe.ear (in root)
  • contents of any jar inside runawfe.ear
  • extension directory wfe.custom (full path is ${JBOSS4_HOME}/server/default/wfe.custom)

Note. Application classpath for Jboss7 includes:

  • contents of any jar inside runawfe.ear
  • extension directory wfe.custom (full path is ${JBOSS7_HOME}/standalone/wfe.custom)

# Override properties

In system base properties are used from "file.properties" included in distributive (usually located in jar inside runawfe.ear) which can be overriden by specified keys from file "wfe.custom.file.properties".

Example for specifying MSSQL Server connection (wfe.custom.database.properties):

hibernate.connection.datasource=java:/mssqlds
hibernate.dialect=ru.runa.wfe.commons.hibernate.SQLServerUnicodeDialect

# Extending xml settings

For almost any XML configuration file there is a rule: base data is used from "file.xml" included in distributive (usually located in jar inside runawfe.ear) + data from file "wfe.custom.file.xml" in the same format.

Example of registering new validator (wfe.custom.validators.xml):

<?xml version="1.0" encoding="UTF-8"?>
<validators>
 <validator name="IntersectedVacationsDataValidator" class="ru.runa.wf.validators.IntersectedVacationsDataValidator"/>
</validators>

# Extending Spring context

Create file wfe.custom.system.context.xml. It allows to override existing beans by IDs and define new beans.

Example of overriding application initialization logic and business calendar implementation:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
 <bean id="executorLogic" class="ru.runa.wfe.user.logic.ExecutorLogic">
  <property name="passwordCheckPattern" value="${strong.passwords.regexp}" />
  <property name="setStatusHandlers">
   <list>
    <bean class="ru.runa.wfe.synchronizer.online.ActorStatusSynchronizer" />
   </list>
  </property>
 </bean>
 <bean id="initializerLogic" class="ru.runa.common.AlfwfInitializerLogic" />
 <bean id="businessCalendar" class="ru.runa.calendar.BusinessCalendarRunaImpl" />
</beans>

Example of overriding application initialization logic and defining new DAO classes:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
  <property name="hibernateProperties" ref="hibernateProperties" />
  <property name="entityInterceptor">
   <bean class="ru.runa.wfe.commons.hibernate.CacheInterceptor" />
  </property>
  <property name="packagesToScan">
   <list>
    <value>ru.runa.wfe</value>
    <value>ru.runa.rkdemo.dao</value>
   </list>
  </property>
 </bean>
 <bean id="organizationDAO" class="ru.runa.rkdemo.dao.OrganizationDAO">
  <property name="hibernateTemplate" ref="hibernateTemplate" />
 </bean>
 <bean id="visitorDAO" class="ru.runa.rkdemo.dao.VisitorDAO">
  <property name="hibernateTemplate" ref="hibernateTemplate" />
 </bean>
 <bean id="roomDAO" class="ru.runa.rkdemo.dao.RoomDAO">
  <property name="hibernateTemplate" ref="hibernateTemplate" />
 </bean>
 <bean id="initializerLogic" class="ru.runa.rkdemo.logic.RkDemoInitializerLogic" />
</beans>

# The list of settings

# Development mode

Settings JVM system property (in bat, sh) devmode to true will turn on development mode. For details see SystemProperties.isDevMode()

# Version 3 backward compatibility mode

To enable execution of business processes designed for version 3 without adapting them set JVM system property (in bat, sh) v3compatibility to true. For details see SystemProperties.isV3CompatibilityMode()

# Base properties (system.properties)

name description default value
version
system version is set from pom.xml on build stage
default.administrator.name
Administrator login created on first system start Administrator
default.administrator.password
Administrator password created on first system start wf
default.administrators.group.name
Administrators group name created on first system start Administrators
default.bots.group.name
Bots group name created on first system start Bots
strong.passwords.regexp
regular expression for user passwords not set
escalation.enabled
whether task escalation enabled true
escalation.default.hierarchy.loader
organization function or relation for task escalation ru.runa.wfe.extension.orgfunction.TestOrgFunction (dummy function)
  • FQCN of organization function
  • @relationName
  • @!relationName for reverse relation
escalation.default.orgFunction
organization function or relation for task escalation before version 4.1.1 ru.runa.wfe.extension.orgfunction.TestOrgFunction (dummy function)
task.default.deadline
if task deadline is not set in process definition (in Developer Studio) then this value is used 2 hours
task.almostDeadlinePercents
for task highlighting tasks in tasklist only 90
authentication.domain.name
domain name TEST
authentication.ldap.server.url
server url ldap://ldapserver.test.com
authentication.ldap.userName.format
it's allowed to use placeholders ${username}, ${domain.name}. ${domain.name}\\${username}
ldap.synchronizer.enabled
users and groups LDAP synchronization false
ldap.connection.provider.url
example: ldap://172.16.100.2/dc=domain,dc=com not set
ldap.connection.principal
example: cn=LdapReader,ou=User_policy,dc=domain,dc=com not set
ldap.connection.password
connection password not set
ldap.synchronizer.ou
example: ou=Admins;ou=User_policy not set
ldap.synchronizer.create.executors
create new executors in the system or only synchronize group membership of existing executors? not set
date.format.pattern
date format pattern in the system (also used in date with time formatting) dd.MM.yyyy
executionServiceAPI.updateVariables.enabled
whether execution of ru.runa.wfe.service.impl.ExecutionServiceBean.updateVariables(User, Long, Map<String, Object>) enabled false 4.1.2+, true 4.1.2-
scriptingServiceAPI.executeGroovyScript.enabled
whether execution of ru.runa.wfe.service.ScriptingService.executeGroovyScript(User, String) enabled false
token.maximum.depth
maximum depth for tokens, to prevent logical errors 100
file.variable.local.storage.enabled
use file system storage for big files true
file.variable.local.storage.path
file system storage path wfe.filedata directory
file.variable.local.storage.enableforfilesgreaterthan
file system storage threshold, in bytes 100000
string.variable.length
don't change please 1024
ear.filename
change if you build your own EAR only runawfe.ear
undefined.variables.allowed
whether undeclared variables (in Developer Studio) enabled false
strong.variables.format.enabled
strong type matching mode. Require strong correspondence to set in Developer Studio variable type when value is assigned true
variables.autocast.enabled
automatically cast variable value to set in Developer Studio variable type in strong type match mode. true
timertask.period.millis.job.execution 4.0.6+
period of checking expired timers of all processes in milliseconds 60000
timertask.start.millis.job.execution 4.0.6+
pause before first execution of expired timers of all processes after system starts in milliseconds 60000
timertask.period.millis.unassigned.tasks.execution 4.0.6+
period of finding unassigned tasks with following assigning (in milliseconds) 60000 4.2.0+ (600000 4.2.0-)
timertask.start.millis.unassigned.tasks.execution 4.0.6+
pause before first finding of unassigned tasks after system starts and following assigning (in milliseconds) 60000
timertask.period.millis.ldap.sync 4.0.6+
period between LDAP synchronizations (in milliseconds) 10800000
timertask.start.millis.ldap.sync 4.0.6+
pause before first LDAP synchronization after system starts (in milliseconds) 600000
receive.message.handle.in.sequence.enabled
only in 4.1.0, see description true
trusted.authentication.enabled 4.2.0+
Whether to enable trusted authentication using service account (AuthenticationService.authenticateByTrsustedPrincipal(User, String)) false
upgrade.process.to.next.definition.version.enabled 4.2.0+
Whether process upgrade to next definition version is enabled (can be useful for blocking process errors, can have unpredictable results if process definitions are strongly differ) false
process.end.handlers 4.3.0+
Process end handlers list invoked on process end
base.process.id.variable.name 4.3.0+
variable name which can contain base process id that can be used in loading variable if it is not defined in current process.

# class.presentation.properties

Displaying objects in tables using filters can be configured here.

# web.properties

name description default value
group.subprocess.enabled
whether in processes list grouping by subprocesses allowed true
task.form.autoShowNext
automatically show next tasks from this process on task completion (if there is only 1 task) false
task.form.highlightRequiredFields
true
task.form.ajaxFileInputEnabled
use custom jquery file upload input which allows to persist files through form validation and clearance of user input true
task.form.external.js.libs 4.2.0+
use external javascript libraries in task forms (semicolon-separated values) not set
view.logs.limit.lines.count
10000
view.logs.timeout.autoreload.seconds
15
process.graph.autoRefreshInterval.seconds
15
process.showGraphMode
there is 2 modes:

1) false. Process graph and data displayed in the same page. 2) true. Process graph and data displayed in the different pages.

false
process.variables.displayJavaType
false
ntlm.enabled
enable NTLM authentication (see link in login page) false
ntlm.domain
MYDOMAIN
confirmation.*
whether to show confirmation popup dialogs on user actions by context
menu.additional_links for details see ru.runa.common.WebResources.getAdditionalLinks() not set
synchronization.ldap.link.enabled
false
synchronization.ldap.create.executors
false
process.definition.ajax.bulk.deployment.enabled 4.2.0+
ability to bulk load process definitions in a batch true
process.removal.enabled 4.2.0+
ability to remove process by administrator false
task.delegation.enabled 4.2.0+
ability to delegate tasks to other people false
process.swimlane.assignment.enabled 4.3.0+
ability to set swimlane executor by administrators false
process.task.filters.enabled 4.3.0+
started processes view contains task filters false


# office.properties

name description default value
docx.placeholder.start
<4.0.6+

${4.0.6-

docx.placeholder.end
>4.0.6+

}4.0.6-

docx.element.start
[
docx.element.end
]

# graph.properties

name description default value
edgingOnly
choose mode: redraw over existing graph image (true) or create new image (false) true
backgroundColor
0xF0FFFF
figureBackgroundColor
0x009900
activeFigureBackgroundColor
0xFFFF66
baseColor
0x000000
textColor
0x000000
transitionColor
0xCCCCCC
highlightColor
0x009900
alarmColor
0xFF3333
lightAlarmColor
0x996633
fontSize
used only for edgingOnly=false mode 9
fontFamily
used only for edgingOnly=false mode Verdana
bpmn.showSwimlane
used only for edgingOnly=false mode true
logs.enabled
whether to show logs on process diagram on mouse over true

# business.calendar.properties

Read more about business calendar

# cache.properties

Caching in RunaWFE is made on logic layer for some entities:

  • task lists with applied substitution rules
  • substitution rules calculated result
  • executor groups, etc
  • parsed process definitions

In smart cache mode only changed objects are recached.

Caching cannot be turned off.

name description default value
smart_cache
enable smart mode true

# botstation.properties

name description default value
botstation.invocation.period.seconds
300 (3 4.3.1-)
botstation.system.username
Administrator
botstation.system.password
wf
thread.pool.size
1
taskhandler.jar.names
it is used to display available task handler classes in web interface (search is made only in these JARs) wfe-bots-*.jar;*wfe-core-*.jar;*wfe-office-*.jar
bot.logger.class
not set
botstations.autostart.enabled 4.2.0+
start all bot stations on system startup false (true 4.3.1-)

# Connecting delegates and services (ejb.properties)

name description default value
ejb.type
local (in the same JVM only) or remote local
ejb.jndiName.format
is set by maven depending from application server type

In case of using remote ejb jndi.properties is required (client jboss libraries required as well)

name description value for jboss4 value for jboss7
java.naming.factory.initial
JNDI factory class name org.jnp.interfaces.NamingContextFactory org.jboss.naming.remote.client.InitialContextFactory
java.naming.provider.url
jnp://localhost:10099 remote://localhost:4447
java.naming.factory.url.pkgs
only for jboss4 org.jboss.naming:org.jnp.interfaces -
jboss.naming.client.ejb.context
only for jboss7 - true

# sql.orgfunction.properties

These settings only for organization functions like SQL*Function (SQLChiefFunction, SQLChiefRecursiveFunction, SQLDirectorFunction, SQLSubordinateFunction, SQLSubordinateRecursiveFunction).

name description default value
datasource
java:/OrgFunctionDS
chief.code.by.subordinate.code.sql
select CHIEF_ID from EMPLOYEES where ID = ?
subordinate.codes.by.chief.code.sql
select ID from EMPLOYEES where CHIEF_ID = ?
get.all.directors.codes.sql
SELECT ID FROM DIRECTORS

# Authentication

In Spring context (system.context.xml) there is bean with id for login modules configuration:

<bean id="loginModuleConfiguration" class="ru.runa.wfe.security.auth.LoginModuleConfiguration">
 <property name="loginModuleClassNames">
  <list>
   <value>ru.runa.wfe.security.auth.InternalDBPasswordLoginModule</value>
   <value>ru.runa.wfe.security.auth.KerberosLoginModule</value>
   <value>ru.runa.wfe.security.auth.PrincipalLoginModule</value>
  </list>
 </property>
</bean>

You can enable required login modules.

# Kerberos authentication

Note. In current section names are case-sensitive.

Create domain user (let's name it as WorkflowUser).

Note. In order to use DES encryption:

  • Open WorkflowUser properties
  • Check 'Use DES encryption'
  • Change user password

Let's use test.com for our domain, wfserver.test.com for our server name; default_realm in krb5.ini is set to TEST.COM. File ${windir}/krb5.ini is required in server and client computers (See details).

Sample krb5.ini

[domain_realm]
 .test.com = TEST.COM
 test.com = TEST.COM
[libdefaults]
 default_realm = TEST.COM
 kdc_timesync = 1
 ccache_type = 4
 ticket_lifetime = 600
 default_tkt_enctypes = des-cbc-md5 des-cbc-crc des3-cbc-sha1
 default_tgs_enctypes = des-cbc-md5 des-cbc-crc des3-cbc-sha1
 permitted_enctypes = des-cbc-md5 des-cbc-crc des3-cbc-sha1
[logging]
 kdc = CONSOLE
[realms]
 TEST.COM = {
  kdc = 192.168.0.1:88
  default_domain = test.com
 }
[appdefaults]
 autologin = true
 forward = true
 forwardable = true
 encrypt = true

We can use utilities setspn and ktpass from Microsoft Support tools. They should be installed in domain controller.

Create SPN (used only for kerberos authentication through web interface):

setspn -A HTTP/wfserver.test.com@TEST.COM TEST\WorkflowUser

ktpass -princ HTTP/wfserver.test.com@TEST.COM -pass password for WorkflowUser -mapuser TEST\WorkflowUser

where TEST is NetBIOS name.

Last command cause warning "WARNING: pType and account type do not match. This might cause problems" but you can ignore it.

In wfserver.test.com create keytab file using ktab from $JAVA_HOME/bin:

ktab -a HTTP/wfserver.test.com@TEST.COM password for WorkflowUser -k C:/krb5.keytab

Copy file from https://github.com/processtech/runawfe-server/blob/master/wfe-core/src/main/resources/kerberos.properties.sample and rename it to kerberos.properties. Configure it.

name description default value
api.auth.enabled
enable kerberos authentication using RunaWFE API true
http.auth.enabled
enable kerberos authentication using HTTP from web interface true
appName
com.sun.security.jgss.accept
moduleClassName
com.sun.security.auth.module.Krb5LoginModule
storeKey
true
useKeyTab
use keytab file true
keyTab
keytab file path C:/krb5.keytab
doNotPrompt
do not prompt credentials true
debug
enable additional logging true
principal
service principal name HTTP/wfserver.test.com@TEST.COM
serverPrincipal
service principal name HTTP/wfserver.test.com
jcifs.http.enableNegotiate
true
sun.security.krb5.debug
enable additional logging true
jcifs.spnego.servicePrincipal
service principal name HTTP/wfserver.test.com@TEST.COM
http.auth.preference
Kerberos

# LDAP authentication

Configure settings: authentication.domain.name, authentication.ldap.server.url, authentication.ldap.userName.format.

# Data source configuration

Persistence layer uses Hibernate ORM so system can work with any database. But we test and provide patches only for the following DBs: PostgreSQL, MS SQL Server, Oracle, HSQL.

Common steps for data source configuration:

  1. registration of the JDBC driver in application server
  2. registration of the data source in application server
  3. binding data source with database.properties and setting appropriate dialect
  4. configuration database for messages (used for message nodes only). TODO: examples

Additional information about properties in file database.properties.

# Database creation

At first RunaWFE startup tables (and sequences) will be created automatically. You should create empty database (or use existing with non-conflicting names) and configure user with appropriate permissions. After database creation the database structure changes only by patches. So it's recommended to use user without DDL permissions.

# Using Jboss4

Note. By default HSQL is configured in Jboss4.

Configuration steps (see details):

  1. place jdbc driver library (*.jar) to $jboss4/server/default/lib
  2. create data source file *-ds.xml in $jboss4/server/default/deploy
  3. configure database.properties

# PostgreSQL

  1. place library postgresql-*.jar in lib
  2. configure postgresql-ds.xml in deploy
  3. in database.properties set hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect, hibernate.connection.datasource=java:/postgresql-ds

postgresql-ds.xml

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
 <xa-datasource>
  <jndi-name>postgres-ds</jndi-name>
  <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
  <xa-datasource-property name="ServerName">localhost</xa-datasource-property>
  <xa-datasource-property name="PortNumber">5432</xa-datasource-property>
  <xa-datasource-property name="DatabaseName">test</xa-datasource-property>
  <xa-datasource-property name="User">postgres</xa-datasource-property>
  <xa-datasource-property name="Password">postgres</xa-datasource-property>
  <track-connection-by-tx></track-connection-by-tx>
 </xa-datasource>
</datasources>

# MySQL

Note. It's recommended to use PostgreSQL instead of MySQL with RunaWFE. RunaWFE works with MySql, but currently we don't supply update patches for it. If you do use MySQL with RunaWFE it's possible to update it manually (but it's not a trivial task). See more here

  1. place library mysql-connector-java-bin.jar in lib
  2. configure mysql-ds.xml in deploy
  3. in database.properties set hibernate.dialect=org.hibernate.dialect.MySQLDialect, hibernate.connection.datasource=java:/mysql-ds

mysql-ds.xml

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
 <local-tx-datasource>
  <jndi-name>mysql-ds</jndi-name>
  <connection-url>jdbc:mysql://YourIp:3306/DEMO_WF_DB?UseUnicode=true&amp;characterEncoding=UTF-8</connection-url>
  <driver-class>com.mysql.jdbc.Driver</driver-class>
  <user-name>yourusername</user-name>
  <password>secret</password>
 </local-tx-datasource>
</datasources>

# MS SQL Server

  1. place library jtds.jar in lib
  2. configure mssql-ds.xml in deploy
  3. in database.properties set hibernate.dialect=ru.runa.wfe.commons.hibernate.SQLServerUnicodeDialect (or org.hibernate.dialect.SQLServerDialect), hibernate.connection.datasource=java:/mssql-ds

mssql-ds.xml

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
 <local-tx-datasource>
  <jndi-name>mssql-ds</jndi-name>
  <connection-url>jdbc:jtds:sqlserver://SQL_SERVER_NAME;databaseName=your_database_name</connection-url>
  <driver-class>net.sourceforge.jtds.jdbc.Driver</driver-class>
  <user-name>yourusername</user-name>
  <password>secret</password>
 </local-tx-datasource>
</datasources>

# Oracle

  1. place library ojdbc.jar in lib
  2. configure oracle-ds.xml in deploy
  3. in database.properties set hibernate.dialect=org.hibernate.dialect.OracleDialect, hibernate.connection.datasource=java:/oracle-ds

For XE version set environment variables in run.bat.

set JAVA_OPTS=%JAVA_OPTS% -Duser.region=us -Duser.language=en

oracle-ds.xml

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
 <local-tx-datasource>
  <jndi-name>oracle-ds</jndi-name>
  <connection-url>jdbc:oracle:thin:@localhost:1521:XE</connection-url>
  <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
  <user-name>wfe</user-name>
  <password>wfe</password>
  <min-pool-size>5</min-pool-size>
  <max-pool-size>20</max-pool-size>
  <idle-timeout-minutes>0</idle-timeout-minutes>
  <track-statements />
  <prepared-statement-cache-size>32</prepared-statement-cache-size>
  <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name>
 </local-tx-datasource>
</datasources>

# Configure database for messages

Messages which are not handled after they are sent from 'SendMessage' nodes are persisted by default in HSQL.

If you want to reconfigure database (see details):

  • from jboss-messaging-1.4.4.GA.zip (jbossmessaging) in examples/config choose file for your DB
  • Copy it to ${RunaWFE}/server/default/deploy/jboss-messaging.sar
  • Change DefaultDS to another name
  • From ${RunaWFE}/server/default/deploy/jboss-messaging.sar delete hsqldb-persistence-service.xml

After WFE Server starts check that there are no errors and in your database tables with prefix JBM_* are created.

# Using Jboss7

Note. By default H2 is used in Jboss7. In older distributives it was configured in in-memory mode.

Configuration steps (see defails):

  1. create module for jdbc driver
  2. register data source in standalone.xml (<subsystem xmlns="urn:jboss:domain:datasources:1.0"><datasources>)
  3. configure database.properties

# PostgreSQL

Create module org.postgresql

Module structure:

modules
\
 - org
  \
   - postgresql
    \
     - main
      \
       - module.xml
       - postgresql-8.4-701.jdbc4.jar

module.xml

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="org.postgresql">
 <resources>
  <resource-root path="postgresql-8.4-701.jdbc4.jar"/>
 </resources>
 <dependencies>
  <module name="javax.api"/>
  <module name="javax.transaction.api"/>
 </dependencies>
</module>

Add sections to standalone.xml

<datasource jndi-name="java:jboss/datasources/PostgreDS" pool-name="PostgreDS">
 <connection-url>jdbc:postgresql://localhost:5432/wfe</connection-url>
 <driver>postgresql</driver>
 <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
 <pool>
  <min-pool-size>10</min-pool-size>
  <max-pool-size>100</max-pool-size>
  <prefill>true</prefill>
 </pool>
 <security>
  <user-name>wfe</user-name>
 </security>
 <validation>
  <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"/>
  <validate-on-match>true</validate-on-match>
  <background-validation>false</background-validation>
  <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter"/>
 </validation>
 <statement>
  <prepared-statement-cache-size>32</prepared-statement-cache-size>
  <share-prepared-statements>true</share-prepared-statements>
 </statement>
</datasource>
<drivers>
 <driver name="postgresql" module="org.postgresql">
  <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
 </driver>
</drivers>

In database.properties set hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect, hibernate.connection.datasource=jboss/datasources/PostgreDS

# Oracle

Create module com.oraclejdbc

Module structure:

modules
\
 - com
  \
   - oraclejdbc
    \
     - main
      \
       - module.xml
       - ojdbc6_g.jar

module.xml

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="com.oraclejdbc">
 <resources>
   <resource-root path="ojdbc6_g.jar"/>
 </resources>
 <dependencies>
   <module name="javax.api"/>
 </dependencies>
</module>

Add sections to standalone.xml

<datasource jndi-name="java:jboss/datasources/OracleDS" pool-name="OracleDS">
 <connection-url>jdbc:oracle:thin:@localhost:1521:XE</connection-url>
 <driver>oracle</driver>
 <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
 <pool>
  <min-pool-size>10</min-pool-size>
  <max-pool-size>100</max-pool-size>
  <prefill>true</prefill>
 </pool>
 <security>
  <user-name>wfe</user-name>
  <password>wfe</password>
 </security>
 <statement>
  <prepared-statement-cache-size>32</prepared-statement-cache-size>
  <share-prepared-statements>true</share-prepared-statements>
 </statement>
 <validation>
  <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker"/>
  <validate-on-match>true</validate-on-match>
  <background-validation>false</background-validation>
  <stale-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleStaleConnectionChecker"/>
  <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter"/>
 </validation>
 <timeout>
  <blocking-timeout-millis>5000</blocking-timeout-millis>
  <idle-timeout-minutes>5</idle-timeout-minutes>
 </timeout>
</datasource>
<drivers>
 <driver name="oracle" module="com.oraclejdbc">
   <xa-datasource-class>oracle.jdbc.driver.OracleDriver</xa-datasource-class>
 </driver>
</drivers>

In database.properties set hibernate.dialect=org.hibernate.dialect.OracleDialect, hibernate.connection.datasource=jboss/datasources/OracleDS

For XE version set environment variables in run.bat.

set JAVA_OPTS=%JAVA_OPTS% -Duser.region=us -Duser.language=en

# Derby

Create module org.apache.derby

Module structure:

modules
\
 - org
  \
   - apache
    \
     - derby
      \
       - main
        \
         - module.xml
         - derby.jar

module.xml

<module xmlns="urn:jboss:module:1.0" name="org.apache.derby">  
   <resources>  
       <resource-root path="derby.jar"/>  
   </resources>  
   <dependencies>  
       <module name="javax.api"/>  
       <module name="javax.transaction.api"/>  
       <module name="javax.servlet.api" optional="true"/>  
   </dependencies>  
</module>

Add sections to standalone.xml

<datasource jndi-name="java:jboss/datasources/DerbyDS" pool-name="DerbyDSPool">
 <connection-url>jdbc:derby:runawfe;restoreFrom=~/backupdirectory/runawfe</connection-url>
 <driver>derby</driver>
 <security>
  <user-name>wfe</user-name>
  <password>wfe</password>
 </security>
</datasource>
<drivers>
 <driver name="derby" module="org.apache.derby"/>
</drivers>

In database.properties set hibernate.dialect=org.hibernate.dialect.DerbyDialect, hibernate.connection.datasource=jboss/datasources/DerbyDS

# SQL Server

Create module net.sourceforge.jtds

Module structure:

modules
\
 - net
  \
   - sourceforge
    \
     - jtds
      \
       - main
        \
         - module.xml
         - jtds-1.2.7.jar

module.xml

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="net.sourceforge.jtds">
 <resources>
  <resource-root path="jtds-1.2.7.jar"/>
 </resources>
 <dependencies>
  <module name="javax.api"/>
  <module name="javax.transaction.api"/>
 </dependencies>
</module>

Add sections to standalone.xml

<datasource jndi-name="java:jboss/datasources/RunawfeDS" pool-name="RunawfeDSPool">
 <connection-url>jdbc:jtds:sqlserver://localhost;DatabaseName=runawfe</connection-url>
 <driver>mssql</driver>
 <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
 <pool>
  <min-pool-size>5</min-pool-size>
  <max-pool-size>30</max-pool-size>
 </pool>
 <security>
  <user-name>wfe</user-name>
  <password>wfe</password>
 </security>
 <validation>
  <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mssql.MSSQLValidConnectionChecker"/>
  <validate-on-match>true</validate-on-match>
  <background-validation>false</background-validation>
 </validation>
</datasource>
<driver name="mssql" module="net.sourceforge.jtds">
 <driver-class>net.sourceforge.jtds.jdbc.Driver</driver-class>
 <xa-datasource-class>net.sourceforge.jtds.jdbcx.JtdsDataSource</xa-datasource-class>
</driver>

In database.properties set hibernate.dialect=org.hibernate.dialect.SQLServerDialect (or ru.runa.wfe.commons.hibernate.SQLServerUnicodeDialect), hibernate.connection.datasource=jboss/datasources/RunawfeDS

# MySQL

Note. It's recommended to use PostgreSQL instead of MySQL with RunaWFE. RunaWFE works with MySql, but currently we don't supply update patches for it. If you do use MySQL with RunaWFE it's possible to update it manually (but it's not a trivial task). See more here

Create module com.mysql

Module structure:

modules
\
 - com
  \
   - mysql
    \
     - main
      \
       - module.xml
       - mysql-connector-java-5.1.7-bin.jar

module.xml

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="com.mysql">
 <resources>
  <resource-root path="mysql-connector-java-5.1.7-bin.jar" />
 </resources>
 <dependencies>  
   <module name="javax.api"/>  
 </dependencies>
</module>

Add sections to standalone.xml

<datasource jndi-name="java:jboss/datasources/RunawfeDS" pool-name="RunawfeDSPool">
 <connection-url>jdbc:mysql://localhost:3306/wfe?UseUnicode=true&characterEncoding=UTF-8&amp;useOldAliasMetadataBehavior=true</connection-url>
 <driver>mysql</driver>
 <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
 <pool>
  <min-pool-size>10</min-pool-size>
  <max-pool-size>100</max-pool-size>
  <prefill>true</prefill>
 </pool>
 <security>
  <user-name>root</user-name>
 </security>
 <validation>
  <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker"/>
  <validate-on-match>true</validate-on-match>
  <background-validation>false</background-validation>
  <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter"/>
 </validation>
 <statement>
  <prepared-statement-cache-size>32</prepared-statement-cache-size>
  <share-prepared-statements>true</share-prepared-statements>
 </statement>
</datasource>
<drivers>
 <driver name="mysql" module="com.mysql">
  <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
 </driver>
</drivers>

In database.properties set hibernate.dialect=org.hibernate.dialect.MySQL5Dialect, hibernate.connection.datasource=jboss/datasources/RunawfeDS

# Performance tuning

Server hardware requirements vary and depend significantly on the number of concurrent users that are accessing the system. You should tune the memory and garbage collection parameters for the JVM as appropriate for your use case.

# JVM settings

Use file run.bat (on Windows) or run.sh on Linux. Change JAVA_OPTS parameters in it.

For example in run.bat edit line

set JAVA_OPTS=%JAVA_OPTS% -Xms128m -Xmx512m

For most cases, tuning the JVM is done with the following steps:

  1. Assign as much RAM as possible for the JVM (-Xmx8GB)
  2. Set the perm gen to 512M (-XX:MaxPermSize:512m -XX:PermSize:512m)
  3. Ensure the "server" VM is used (-server)

To avoid memory swapping -Xmx should never exceed the amount of available RAM in the system. Remember to leave room in memory for the OS and other applications.

In general, if you don't give the JVM enough heap space, playing with other JVM settings will not help. Once the JVM has enough heap space, playing with other JVM settings influence performance much.

The following settings are used on a home server 32-bit, dual-core per CPU, 4GB RAM environment.

-server -Xms512m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintConcurrentLocks -XX:MaxPermSize=256m
-server -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+CMSClassUnloadingEnabled -Xms512m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintConcurrentLocks -XX:MaxPermSize=256m

Example for multi-CPU 64-bit 8GB server

-server -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -Xms1g -Xmx4g -Xss256k -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintConcurrentLocks

Optiona to turn on parallel garbage collector

-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+ParallelRefProcEnabled -XX:NewRatio=5 -XX:+CMSScavengeBeforeRemark

Optiona to turn on parallel garbage logging and tracing

-XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:"../server/default/log/gc.log"

# How to get memory and stack dumps for performance analysis

# Using JDK utilities

Change to folder ${JDK}\bin\.

In order to get memory dump run command:

jmap -dump:format=b,file=heap.bin pid,  where pid is the process identifier

In order to get stack dump run command:

jstack pid,  where pid is the process identifier

If it doesn't work and problems like "Insufficient memory space to run command" occur, it is recommended to use one of the ways described below:

# Using JavaMelody

In version 4 javamelody is included in distributive and available at http://localhost:8080/wfe/monitoring. The performance drop can be up to 30%.

Project url: http://code.google.com/p/javamelody/

This tool allows not only to get memory dumps but it can also help to analyze the system behavior. The additional load is small and it makes it possible to use this tool on production server while it works as usual.

This interface helps to find system performance bottlenecks and to make dumps.

Stack dump can be obtained from interface using "Threads -> Details -> Dump threads as text".

Memory dump can be obtained from interface using "Generate a heap dump".

To disable javamelody:

  1. comment line hibernate.jdbc.factory_class=net.bull.javamelody.HibernateBatcherFactory in database.properties
  2. in web.xml comment or delete fragment
<filter>
 <filter-name>monitoring</filter-name>
 <filter-class>net.bull.javamelody.MonitoringFilter</filter-class>
</filter>
<filter-mapping>
 <filter-name>monitoring</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
 <listener-class>net.bull.javamelody.SessionListener</listener-class>
</listener>

# Using VisualVM

Project url: visualvm.java.net

If you run VisualVM on the same computer as WFE and VisualVM finds WFE process then no further configuration is needed.

If you run VisualVM on the other computer or VisualVM couldn't find the WFE process (as it usually happens if these programs run under different users) then following configuration is needed:

JAVA_OPTS variable should be configured in run.bat (Windows) or in run.sh (Linux).

For example it can be done like that:

set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote.port=6767 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false

Ensure that port 6767 is not blocked by Firewall.

JMX Connection is used to connect with VisualVM.

After successful connection popup menu on right mouse click contains options Thread Dump, Heap Dump. Also this tool helps to monitor the process. It is unadvised to leave the connection open for a long time in production mode because of the constant data sending from JVM to VisualVM.

# Settings for message nodes (ReceiveMessage, SendMessage)

# In Jboss 4

JbossMessaging is used. See details in project documentation.

Base settings are located in runawfe.ear!/runawfe-jms-service.xml

Parameter /server/mbean/attribute[name="DefaultMaxDeliveryAttempts"] is used for maximum redelivery attempt while receiver is not active.

Parameter /server/mbean/attribute[name="DefaultRedeliveryDelay"] is used for timeout between redelivery attempts.

With parameters DefaultMaxDeliveryAttempts=43200, DefaultRedeliveryDelay=60000 TTL of the message will be 1 month and timeout between redelivery attempts 1 minute.

# In Jboss 7

HornetMQ is used. See details in project documentation.

# Other settings

# User session timeout

To change default timeout (30 minutes) add in file ${RunaWFE}/server/default/deploy/wfe.war!/WEB-INF/web.xml section <web-app> like

<session-config>
   <session-timeout>N</session-timeout>
</session-config>

where N is minutes count (0 means unlimited timeout).

# Notifications about new tasks

In system.context.xml for bean taskFactory set property taskNotifier.

Example

<bean id="taskFactory" class="ru.runa.wfe.task.TaskFactory">
 <property name="defaultTaskDeadline" value="${task.default.deadline}" />
 <property name="taskNotifier">
  <bean class="ru.runa.wfe.task.EmailTaskNotifier"> 
   <property name="configLocation" value="email.config.xml" />
   <property name="onlyIfTaskActorEmailDefined" value="true" />
  </bean> 
 </property>
</bean>

Sample email.config.xml

<?xml version="1.0" encoding="UTF-8"?>
<email-config>
 <common>
   <param name="throwErrorOnFailure" value="true"/>
 </common>
 <headers>
   <param name="From" value="SMTPbot@robots.runa.ru"/>
   <param name="To" value="${task.executor.email}"/>
 </headers>
 <connection>
   <param name="mail.transport.protocol" value="smtp"/>
   <param name="mail.host" value="172.16.100.7"/>
   <param name="mail.smtp.port" value="25"/>
 </connection>
 <message>
   <param name="bodyInlined" value="true"/>
 </message>
</email-config>

Parameters of the ru.runa.wfe.task.EmailTaskNotifier includes:

  • configLocation (required) - email configuration for notifications
  • enabled (default value = true) - enable notifications
  • onlyIfTaskActorEmailDefined (default value = false) - send notifications by tasks assigned to user with valid email

In message body you can use context variables

User form interaction (${interaction}, ru.runa.wfe.form.Interaction)

Use javascript validation		${interaction.useJSValidation?string("yes", "no")}
Required fields list			${interaction.requiredVariableNames}
Form code as byte[]	 		${interaction.formData}

Recipients (${emails}, java.lang.String)

This string is formed from valid user emails who can be task executor (multiple users in case of group assignment).

Task (${task}, ru.runa.wfe.task.Task)

ID					${task.id}
Node ID 				${task.nodeId}
Name 					${task.name}
Description 				${task.description}
Role name    				${task.swimlane.name}
Executor				${task.executor.label}
Createion date		    		${task.createDate?datetime}
Deadline date    			${task.deadlineDate?datetime}

Process (${task.process}, ru.runa.wfe.execution.Process)

ID					${task.process.id}
Start date				${task.process.startDate?datetime}
End date 				${task.process.endDate?datetime} (only for async tasks)
Subprocess IDs				${task.process.hierarchyIds}

Process definition (${task.process.deployment}, ru.runa.wfe.definition.Deployment)

ID					${task.process.deployment.id}
Version 				${task.process.deployment.version}
Name					${task.process.deployment.name}
Description				${task.process.deployment.description}
Category				${task.process.deployment.category}
Deployed				${task.process.deployment.createDate?datetime}

# Changing ports

# In Jboss 4

1) HTTP port (8080) is used to access system via browser. It can be changed in ${RunaWFE}/server/default/deploy/jbossweb-tomcat55.sar/server.xml in one place <Connector port="8080" ...

2) JNDI ports (10098/10099) are used for server resources look-ups. For example when EJB is called it is being looked up in JNDI catalog. It is necessary not only change port number in ${RunaWFE}/server/default/conf/jboss-service.xml server configuration file, but also all clients settings must be changed. It must be done in Developer Studio (if server connection feature is used there), Task Notifier, client side of the server (files jndi.properties). For correct bot station work change port number in RMI address (E.g. to set 10099 port write localhost:10099)

3) RMI ports (4444, 4445). It can be changed in ${RunaWFE}/server/default/conf/jboss-service.xml.

# In Jboss 7

TODO

# Logging

Logging is based on log4j.

By default there are files in log directorty:

  • boot.log – jboss boot protocol
  • server.log – jboss execution protocol

Configuration is done in file conf/jboss-log4j.xml (jboss4) or standalone.xml (jboss7).