When a Flowable script task is the right tool
A Flowable script task runs a short piece of script code inside a BPMN process step. The language is named in the scriptFormat attribute, which must be the name of a JSR-223 compatible script engine, and the script reads and writes process variables while the step runs. Teams reach for it when a BPMN model needs a small amount of logic between tasks, such as setting a flag, computing a due date from a field, or choosing a value to pass to the next gateway, and the logic is simple enough that it reads better in the model than in a separate class. The Flowable engines are Apache 2.0 Java engines for BPMN, CMMN and DMN that run embedded in your application, so the script executes inside the same JVM and transaction context as the rest of the process. Confirm the exact element and attribute behavior against the Flowable BPMN 2.0 constructs documentation before you standardize on it.
Script tasks suit logic that is short, stable and owned by the people who read the model. Business analysts can often see what a script does when it sits in the diagram, which helps reviews. The trade-off is that scripts are text stored in the process definition, so they are harder to unit test, harder to reuse across processes, and easier to change without a code review. Before you model a script task, ask who will maintain the logic, whether the same rule appears in other processes, and whether the logic needs to call services, databases or libraries. If the answer to the last question is yes, or the logic grows past a few lines, plan a Java delegate instead. The sections that follow cover language choice, the JavaScript engine on modern JDKs, variable handling and results.
Script languages and when each option fits
This table compares the three ways to put logic into a Flowable service step: a Groovy script task, a JavaScript script task with an engine you add yourself, and a Java delegate or expression. Read each row against your team's skills, how you test and review the logic, and what the runtime must carry. The main takeaway is that scripts suit small, reviewed variable logic, while anything substantial usually belongs in compiled Java code.
| Factor | Groovy script task | JavaScript script task | Java delegate or expression |
|---|---|---|---|
| Team skills | Suits Java teams who already read Groovy | Suits teams with JavaScript skills, but the engine must be added first | Suits Java developers who own the process application |
| Testability | Scripts run inside the engine, so tests must deploy the model | Same constraint as Groovy, with an extra engine to exercise in tests | Delegates are plain classes that unit tests can call directly |
| Code review | Script text sits inside BPMN XML, which reviewers must read carefully | Same review burden as Groovy, and fewer reviewers may read it fluently | Changes go through normal Java review and build tooling |
| Runtime dependencies | Needs the groovy-jsr223 dependency on the classpath | Needs a JSR-223 JavaScript engine added explicitly on JDK 17 or later | Needs only the application's own classes and the engine APIs |
| JDK baseline | Works on the JDK you run Flowable on, subject to the Groovy version you add | Not bundled, because Nashorn was removed in JDK 15 under JEP 372 | No scripting engine required |
| Best fit | Short variable mapping or conditions in a Groovy-literate team | Teams standardizing on JavaScript who accept the extra dependency | Calls to services, database work, error mapping or anything reused across models |
Adding Groovy or JavaScript to a Flowable engine
This sequence takes a Flowable deployment from a bare JDK to a tested script task that reads and writes process variables, so you can confirm the scripting setup works before any business logic depends on it.
Confirm the JDK and Flowable versions
The platform engineer or lead developer checks the JDK on build agents and runtime hosts and records the Flowable engine version the project uses. Flowable runs on JDK 17 or later, and OpenJDK JEP 372 removed the Nashorn JavaScript engine in JDK 15, so a JavaScript script task will not run on the JDK alone. Done when the build and runtime JDK versions match in every environment and are written into the project README.
Add the Groovy script engine dependency
The developer adds the groovy-jsr223 dependency to the build file for the application that embeds the Flowable engine, so Groovy is available to the JSR-223 lookup at runtime. For JavaScript, the developer adds a JSR-223 compatible JavaScript engine explicitly, because none ships with the JDK in this setup. Confirm the chosen JavaScript engine's license, maintenance status and compatibility with your JDK with its maintainer before adding it. Verify by running a dependency tree command and confirming the engine appears on the runtime classpath.
Set scriptFormat in the process model
The process modeler sets the scriptFormat attribute on the script task to the JSR-223 engine name, such as groovy for Groovy, and writes the script body in the task. The scriptFormat value must match an engine the classpath can resolve, so a misspelled name fails when the task runs rather than when the model is saved. Check the exact engine name against the Flowable BPMN constructs documentation before committing the model, and confirm the BPMN file validates in the modeler.
Deploy a small test process
The developer deploys a minimal test process that contains one script task with a simple expression, such as reading an input variable and setting an output variable, along with a start event and end event. Use an in-memory H2 database for this test so the check runs without shared infrastructure. Confirm the deployment appears in the process definition list and that starting an instance does not raise a script engine lookup error in the logs.
Assert variable reads and writes in a unit test
The developer writes a unit test that starts the test process with known input variables, lets the engine run the script task synchronously, and asserts the output variable equals the expected value. Include one case with a null or missing input so the behavior is explicit. Done when the test passes in the build pipeline and fails if the script engine is removed from the classpath, which confirms the test really exercises the script.
Check script results and variable types
The developer extends the test to read the script result and confirm its Java type, since script languages return values that the engine stores as process variables. Verify that dates, numbers and collections round-trip as the downstream expression expects. Record any type conversions the team relies on in the test, so a later engine upgrade or script change shows up as a failing assertion instead of a silent data change.
Review the approach before wider use
The lead developer and security reviewer confirm that the team has a documented reason to use a script task rather than a Java delegate for each piece of logic, and that the script sources are under version control and reviewed like code. They also confirm that the scripting engines allowed in each environment are the ones the review approved. Done when the test suite, the dependency list and the approved engine list are recorded together in the project's documentation.
Security risks of inline script code
Script tasks let a process definition carry executable code, so the people who can deploy or edit models effectively control what runs on your engine. The cards below separate the risks that come from who can change a model, what data scripts read, what the host JVM exposes, and how scripts get reviewed before release.
Who can deploy or edit models
A script task stored in a BPMN file runs with the same rights as the engine process. Anyone who can upload a process definition through the REST API or your deployment pipeline can add script code, so deployment rights are a code-execution right. Check who holds deployment permissions, whether the model repository enforces review before deployment, and whether modelers can deploy directly to production. Authentication and authorization on the engine APIs are covered in the Flowable security topic.
Script injection through process variables
When a script string is built from process variables, values supplied by users or external systems can change what the script does. An expression such as a variable concatenated into a script body is code, not data. Prefer scripts that read variables by name and treat them as values, and avoid building script text at runtime from request data. Test with hostile input such as quotes, braces and language-specific syntax in every variable a script reads.
Access to the host classpath
Groovy and JavaScript engines can reach Java classes available on the engine's classpath, including file, network and process APIs unless your runtime restricts them. Review which libraries ship with the application, which credentials and configuration beans are reachable from the engine's process, and whether the service account that runs the engine has more access than the process logic needs. Confirm the exact sandbox behavior of the script engine version you deploy, since the Flowable facts supplied do not describe one.
Scripts reviewed like code
Treat every script task body as source code that needs a code review, version control history and tests before it reaches production. Store scripts with the process definition in Git, require a second reviewer for changes, and keep the review checklist visible to modelers. Reviewers should check variable reads and writes, external calls, error handling and whether the logic could move into a tested Java delegate instead.
Script logic in the engine audit trail
Deployed definitions and their script bodies become part of the evidence you may need after an incident. Confirm that deployments record who uploaded a definition, which version ran for each instance, and where the script text is retained. Ask your team how a previous version of a script can be retrieved for investigation, and whether history data is kept long enough to answer those questions.
When a Java delegate is the better place for logic
A Java delegate is usually the better home for logic that is complex, shared, calls external systems or must be tested like the rest of your application code. A script task keeps a small transformation close to the model, but every line of it lives in the BPMN XML, outside the compiler and outside the review and build pipeline your developers already use. The practical question is therefore not whether a script can do the work, but whether the work will still be easy to change, test and secure in two years.
Java delegates are compiled, covered by unit tests, reviewed in the same pull requests as the rest of your code and built with the dependency scanning and signing controls your organization already applies to application artifacts. A script is interpreted at runtime, so a typo or a changed variable name may surface only when a token reaches that step in production. Scripts also tend to accumulate calls to services, shared helper code and copied snippets across many process definitions, which is exactly where a Java class with a clear owner and version history works better. Ask your security team which of these controls apply to process definitions, not only to application code, before you accept scripts into the model.
Keep scripts for short, stable transformations such as setting a flag, formatting a value or computing a simple total from variables that the engine already holds. Move anything that calls an HTTP API, reads a database, branches heavily or needs to be shared across processes into a delegate, and reference the sibling topic on Flowable Java service tasks, delegates and expressions for how to wire it, inject fields and reuse services inside a JavaDelegate.
Limits to confirm in your environment
Script tasks depend on the Flowable version, the JDK and the script engines packaged with your application. Each card below is a question to answer with the Flowable docs or a test environment before you commit to scripts as a production pattern.
Which Flowable version and JDK you run
Confirm which Flowable release line your project uses and which JDK it targets. Flowable 7 moved to Java 17, and Flowable 8 moved the Spring baseline to Spring Framework 7 and Spring Boot 4, so script behavior and dependency choices can differ between lines. Ask whether your runtime JDK matches the one your build was tested against, and record both versions in your architecture decision.
Which script engines your build includes
Check which JSR-223 engines are on the classpath of the deployed artifact, not only in the developer's IDE. Groovy requires the groovy-jsr223 dependency, and JavaScript is not bundled with recent JDKs, so a script with scriptFormat set to javascript can fail only in production if the engine was never added. Confirm this with a startup or deployment test that runs one script per language.
Script evaluation cost under load
Ask how script evaluation performs when the same process definition runs at volume. Scripts compiled on each execution, and scripts that load libraries or call remote services, can add latency and memory pressure on the async executor threads. Measure throughput with realistic variable sizes in a test environment, and compare it against a Java delegate that runs the same logic.
Behavior of script errors in your version
Confirm how a thrown exception in a script task surfaces in your engine version. Check whether the failure rolls back the transaction, creates a failed job subject to retry settings, or reaches an error boundary event as a BPMN error. Test a deliberate exception in a staging environment and verify the job history, retry count and the variable state the process leaves behind.
Script sandboxing and resource access
Confirm what a script can reach on the JVM, including the file system, network sockets, system properties and the Flowable services objects it receives. Scripts run with the permissions of the engine process, so confirm whether your deployment policy restricts them and whether process definitions can be edited by users who should not run code. Document the answer as a security requirement.
Operational visibility of script failures
Check how your monitoring surfaces script failures. Confirm which log categories capture script exceptions, whether stack traces include the script source line, and whether failed jobs appear in the management API or the actuator endpoint you plan to alert on. Set an owner for failed jobs before go-live so errors do not wait in the database unnoticed.
Questions teams ask before writing script tasks
Can our own developers write Flowable script tasks without outside help?
Yes, in most teams that already run Java services, a developer who knows the Flowable BPMN docs can write simple script tasks. The harder part is the surrounding discipline: choosing a script language, packaging its dependencies, keeping scripts short, and testing them outside the running process. Teams often do the first few scripts alone and then ask for a review of their security and dependency choices before scripts multiply. Outside help usually pays off most at the design stage, when the team has to decide which logic belongs in a script and which belongs in a tested Java class.
What drives the effort of a script task project?
The main drivers are the number of scripts, how much logic each one holds, and how much testing and review they need. Effort rises when scripts read and write many process variables, call external systems, or make decisions that affect money, access or regulated records. Other drivers are the JDK version, the choice of script engine and its dependencies, and whether the platform team already has a deployment pipeline that can ship process definitions with their supporting libraries. Ask any provider to break the quote into design, build, test, security review and handover so you can see which drivers apply to your models.
Do we need JavaScript or Groovy for Flowable script tasks?
Pick the language your engineers can review and maintain, then add its engine deliberately. Flowable script tasks name their language in scriptFormat, and the language must be a JSR-223 compatible engine name. Groovy needs the groovy-jsr223 dependency on the classpath. JavaScript is not something to assume: the Flowable BPMN docs note that JavaScript ships with every JDK, but JEP 372 removed the Nashorn engine in JDK 15, and Flowable runs on JDK 17 or later, so a JavaScript engine must be added explicitly. Standardizing on one language keeps the review burden and dependency list smaller.
What does the client need to provide for a script task engagement?
Plan to provide a JDK version that matches your Flowable release, build access to the repository that holds the process models and Java code, and a test environment with a database that matches production. Named reviewers from application security and the process owner are also needed, because scripts often encode business rules. Ask for access to existing process definitions, the dependency management approach, and your deployment pipeline. Confirm these items in writing before work starts, since missing access is one of the most common reasons script work slips.
How do we check that a script is safe before it reaches production?
Treat each script as code: keep it in version control, review it, and test it against realistic variable sets in an automated test suite. Review should check what the script can reach, how it handles null or unexpected variable types, and whether it writes data that other steps rely on. Scripts that accept input from users or external messages need extra review, because a script runs with the privileges of the engine. The Flowable security documentation covers scripting and XML risks, so have your security reviewer read it alongside your own threat model before approving any script language.
When is a Java delegate a better place for the logic than a script?
A Java delegate is usually the better choice when the logic is reused across models, needs unit tests with mocks, calls external services, or touches money, identity or regulated records. Delegates are compiled, type-checked and easier to review with standard Java tooling, while scripts are interpreted at runtime and can hide errors until a process reaches that step. Keep scripts for short, local transformations of variables, such as setting a flag or formatting a value. Ask your provider to show which steps would move to delegates and how the team will test them.
Does a script task project cover compliance evidence for audits?
A script task project can produce the controls and evidence auditors ask for, including version-controlled scripts, documented review decisions, and test results. It does not produce an audit report or certification. Independent auditors and certification bodies decide whether your controls meet a requirement. Ask a provider to explain what evidence each script produces, where it is stored, and who owns its retention, so your compliance lead can judge whether the record is sufficient for the controls in scope.
Where to read the Flowable and JDK sources
Before you write your first script task, read the BPMN 2.0 constructs page in the Flowable docs, since it defines how script tasks, service tasks and the variables they touch are modeled in the engine. Keep it open next to your own process models so you can check each element's attributes against the engine's documented behavior rather than against memory or an older tutorial. Pay particular attention to how the scriptFormat attribute is interpreted, because that is where the language choice for your team is actually made.
The JavaScript question is a JDK question, not a Flowable one. Read the text of OpenJDK JEP 372 to confirm when the Nashorn engine was removed and what the JEP says about alternatives. Then check which JDK your platform team has standardized on and whether any JSR-223 script engine is present in that runtime image. Do not assume a JavaScript engine exists because an older JDK once shipped one. Ask your platform team to confirm the exact JDK build used in every environment, including the container base image and any air-gapped mirror.
For product context, including what the open-source engines cover and where the commercial Flowable products and professional services start, read the Flowable open source documentation introduction. It explains the scope of the open-source project without requiring you to evaluate any commercial tier. Use it to decide which questions belong to the community and which need a written scope from a partner before your team commits to a script-heavy design.
How DeployOpen scopes Flowable script task work
DeployOpen plans, implements, documents and supports self-hosted open-source platforms inside your own infrastructure, and that includes the script tasks in your Flowable models. We agree the scope in writing before work starts, so the language choices, script logic and handover material are settled before anyone writes a script.
How we scope
- Inventory every script task and state its language, purpose and the variables it reads and writes.
- Decide with you whether Groovy, JavaScript or a Java delegate fits each piece of logic.
- Confirm the JDK version and whether a JavaScript engine must be added explicitly to your runtime.
- Record the written scope, deliverables and timeline before any model or script changes begin.
How we build
- Add the Groovy JSR-223 dependency and any JavaScript engine to the classpath, then verify each script language loads.
- Move complex or external-facing logic into Java delegates where that makes testing and review simpler.
- Write scripts that read and set process variables explicitly, with defined result handling and error paths.
- Test script tasks in unit and process-level tests against the Flowable engine version you run.
How we hand over
- Document each script task, its language, its variables and the reason it was chosen over a delegate.
- Provide dependency and classpath notes for Groovy and JavaScript so your team can reproduce the setup.
- Walk your engineers through the test suite, the deployment steps and the review checklist for new scripts.
- Deliver source, configuration and test code in your repositories, with ownership agreed in writing.
How we support
- Ongoing support, upgrades and continuous testing are available as a retainer after handover.
- Review script changes when Flowable versions or JDK baselines change, before they reach production.
- Confirm with your team which script logic should be retested after each Flowable upgrade.
- Quotes follow from the written scope, so ask for the support tier that matches your change volume.

