ServerConfigurationGuide
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)
|
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 |
|
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:
- registration of the JDBC driver in application server
- registration of the data source in application server
- binding data source with database.properties and setting appropriate dialect
- 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):
- place jdbc driver library (*.jar) to $jboss4/server/default/lib
- create data source file *-ds.xml in $jboss4/server/default/deploy
- configure database.properties
# PostgreSQL
- place library postgresql-*.jar in lib
- configure postgresql-ds.xml in deploy
- 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
- place library mysql-connector-java-bin.jar in lib
- configure mysql-ds.xml in deploy
- 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&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
- place library jtds.jar in lib
- configure mssql-ds.xml in deploy
- 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
- place library ojdbc.jar in lib
- configure oracle-ds.xml in deploy
- 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):
- create module for jdbc driver
- register data source in standalone.xml (<subsystem xmlns="urn:jboss:domain:datasources:1.0"><datasources>)
- 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&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:
- Assign as much RAM as possible for the JVM (-Xmx8GB)
- Set the perm gen to 512M (-XX:MaxPermSize:512m -XX:PermSize:512m)
- 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:
- comment line hibernate.jdbc.factory_class=net.bull.javamelody.HibernateBatcherFactory in database.properties
- 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).