Java Programming Extensions
Create a Custom Project
Flowable Work and Engage applications are based on Spring Boot and therefore require it as a base for any development environment.
Check-out the setup page in case you haven't setup your environment yet.
Spring Boot Skeleton
The easiest way to set up a project is to generate a Flowable Project by using the Flowable Initializr.
Generate a project with the Flowable Work, Frontend, Inspect, actuator, and DB of your choice as dependencies. If you want to manually create a project or a project using the Spring Initializr then also read the following sections:
- Dependency Management
- Flowable Work Dependencies
- Flowable Engage Dependencies
- Embedded Front End
- Demo Dependencies
- Java Configuration
Otherwise, you can skip directly to the User Definitions section
Dependency Management
With the help of Maven dependency management, you can delegate the specifying of the correct versions of all the dependencies to a BOM (Bill of Materials). The BOM defines and provides all the specific version information for all direct and transient dependencies. You need to define the to-be-used Flowable version one by to use the correct BOM.
Add the following section to the pom.xml file of the project you just
created as a child tag of the <project> tag:
<dependencyManagement>
<dependencies>
<!-- Imports the bill-of-materials POM. -->
<dependency>
<groupId>com.flowable</groupId>
<artifactId>flowable-platform-bom</artifactId>
<version>${com.flowable.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Choose the Flowable version either by replacing the
${com.flowable.platform.version} part with a Flowable version
number or by defining an appropriate Maven parameter
specifying the version you require.
Flowable Work Dependencies
Flowable Work utilizes multiple maven dependencies to access the required Flowable services.
Depending on the project needs add the following dependencies to set up a Flowable Work project.
<!-- Flowable Work Mandatory -->
<!-- =============== -->
<!-- REST and Java APIs to run headless Flowable Work -->
<dependency>
<groupId>com.flowable.platform</groupId>
<artifactId>flowable-spring-boot-starter-platform-rest</artifactId>
</dependency>
<!-- Flowable Work Recommended -->
<!-- =============== -->
<!-- Contains all Flowable Actuator and Spring Boot Actuator configuration -->
<dependency>
<groupId>com.flowable.platform</groupId>
<artifactId>flowable-spring-boot-starter-platform-actuator</artifactId>
</dependency>
<!-- Flowable Work Optional -->
<!-- =============== -->
<!-- Support loading users from a tenant json file -->
<dependency>
<groupId>com.flowable.platform</groupId>
<artifactId>flowable-tenant-setup</artifactId>
</dependency>
<!-- Default models provided by the product for Flowable Work -->
<dependency>
<groupId>com.flowable.platform</groupId>
<artifactId>flowable-platform-default-models</artifactId>
</dependency>
Flowable Engage Dependencies
Flowable Engage utilizes multiple maven dependencies to access the required Flowable services.
Depending on the project needs, add the following dependencies to set up a Flowable Engage project:
<!-- Flowable Engage Mandatory -->
<!-- =============== -->
<!-- REST and Java APIs to run headless Flowable Engage -->
<dependency>
<groupId>com.flowable.engage</groupId>
<artifactId>flowable-spring-boot-starter-engage-rest</artifactId>
</dependency>
<!-- Flowable Engage Recommended -->
<!-- =============== -->
<!-- Contains all Flowable Actuator and Spring Boot Actuator configuration -->
<dependency>
<groupId>com.flowable.platform</groupId>
<artifactId>flowable-spring-boot-starter-platform-actuator</artifactId>
</dependency>
<!-- Flowable Engage Optional -->
<!-- =============== -->
<!-- Support loading users from a tenant json file -->
<dependency>
<groupId>com.flowable.platform</groupId>
<artifactId>flowable-tenant-setup</artifactId>
</dependency>
<!-- Default models provided by the product for Flowable Work -->
<dependency>
<groupId>com.flowable.platform</groupId>
<artifactId>flowable-platform-default-models</artifactId>
</dependency>
<!-- Default models provided by the product for Flowable Engage -->
<dependency>
<groupId>com.flowable.engage</groupId>
<artifactId>flowable-engage-default-models</artifactId>
</dependency>
If you are using Flowable Engage with a third party messaging services then add the appropriate dependency matching your provider from the example below:
<!-- Flowable Engage 3rd Party Messaging -->
<!-- =============== -->
<dependency>
<groupId>com.flowable.engage</groupId>
<artifactId>flowable-spring-boot-starter-engage-external-whatsapp</artifactId>
</dependency>
<dependency>
<groupId>com.flowable.engage</groupId>
<artifactId>flowable-spring-boot-starter-engage-external-wechat</artifactId>
</dependency>
<!-- ActiveMQ JMS implementation -->
<!-- =============== -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
Flowable Inspect Dependencies
To add Flowable Inspect to your application, add the following dependency:
<dependency>
<groupId>com.flowable.inspect</groupId>
<artifactId>flowable-spring-boot-starter-inspect-rest</artifactId>
</dependency>
Then enable it with the following property:
flowable.inspect.enabled=true
Note that you need an appropriate license to enable Flowable Inspect. In addition to that it is not recommended to enable Flowable Inspect in your production environment.
Embedded Front End
Flowable provides a dedicated JavaScript front end that can either be deployed to any HTML capable server or run embedded directly within the Flowable Server.
To run the front end embedded within the Flowable Server, add the following
dependency to the pom.xml file of the project:
<dependency>
<groupId>com.flowable.work</groupId>
<artifactId>flowable-work-frontend</artifactId>
</dependency>
The front end provides user interfaces for both Flowable Work and Flowable Engage. The Engage user interface is deactivated if only Work features are available.
Demo Dependencies
In case you want to set up a demo project with some default users and default user definitions, you can add the following dependencies:
Flowable Work Demo Dependencies.
<dependency>
<groupId>com.flowable.platform</groupId>
<artifactId>flowable-platform-default-idm-models</artifactId>
</dependency>
<dependency>
<groupId>com.flowable.platform</groupId>
<artifactId>flowable-platform-example-apps</artifactId>
</dependency>
Flowable Engage Demo Dependencies.
<dependency>
<groupId>com.flowable.engage</groupId>
<artifactId>flowable-engage-default-idm-models</artifactId>
</dependency>
<dependency>
<groupId>com.flowable.engage</groupId>
<artifactId>flowable-engage-example-apps</artifactId>
</dependency>
Without the flowable-platform-default-idm-models or flowable-engage-default-idm-models dependency your system won't have any user definitions and users.
This means that you can't sign in to Flowable.
In this case, please remember to configure the User Definitions and Tenant Configuration.
Java Configuration
Before starting the application you need to add some Java configuration classes.
Main Class Configuration
If you are creating a Flowable Engage application, then annotate the main class
with @EnableWebSocketMessageBroker as well.
Application Security Configuration
Next, to the main application, add the following Security configuration for the main application.
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
import com.flowable.autoconfigure.security.FlowableHttpSecurityCustomizer;
import com.flowable.autoconfigure.security.servlet.PlatformPathRequest;
import com.flowable.core.spring.security.web.authentication.AjaxAuthenticationFailureHandler;
import com.flowable.core.spring.security.web.authentication.AjaxAuthenticationSuccessHandler;
import com.flowable.platform.common.security.SecurityConstants;
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
public class SecurityConfiguration {
@Bean
@Order(10)
public SecurityFilterChain basicDefaultSecurity(HttpSecurity http, ObjectProvider<FlowableHttpSecurityCustomizer> httpSecurityCustomizers) throws Exception {
for (FlowableHttpSecurityCustomizer customizer : httpSecurityCustomizers.orderedStream().toList()) {
customizer.customize(http);
}
http
.logout(logout -> logout.logoutUrl("/auth/logout").logoutSuccessUrl("/"))
// Non authenticated exception handling. The formLogin and httpBasic configure the exceptionHandling
// We have to initialize the exception handling with a default authentication entry point in order to return 401 each time and not have a
// forward due to the formLogin or the http basic popup due to the httpBasic
.exceptionHandling(exceptionHandling -> exceptionHandling.defaultAuthenticationEntryPointFor(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED),
AnyRequestMatcher.INSTANCE))
.formLogin(formLogin -> formLogin
.loginProcessingUrl("/auth/login")
.successHandler(new AjaxAuthenticationSuccessHandler())
.failureHandler(new AjaxAuthenticationFailureHandler()))
.authorizeHttpRequests(configurer -> configurer
.requestMatchers(PlatformPathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults());
return http.build();
}
}
By default, a remember-me cookie is used and no session context stored. If you wish to disable the remember-me cookie feature, you will need to provide a session security context repository.
Actuator Security Configuration
Next, to the main application, add the following Security configuration for the actuator endpoints.
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.boot.actuate.health.HealthEndpoint;
import org.springframework.boot.actuate.info.InfoEndpoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import com.flowable.actuate.autoconfigure.security.servlet.ActuatorRequestMatcher;
import com.flowable.platform.common.security.SecurityConstants;
@Configuration
public class SecurityActuatorConfiguration {
@Bean
@Order(6) // Actuator configuration should kick in before the Form Login there should always be HTTP basic for the endpoints
public SecurityFilterChain basicActuatorSecurity(HttpSecurity http) throws Exception {
http
.sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.csrf(AbstractHttpConfigurer::disable);
http
.securityMatcher(new ActuatorRequestMatcher())
.authorizeHttpRequests(configurer -> configurer
.requestMatchers(EndpointRequest.to(InfoEndpoint.class, HealthEndpoint.class)).permitAll()
.requestMatchers(EndpointRequest.toAnyEndpoint()).hasAuthority(SecurityConstants.ACCESS_ACTUATORS)
.anyRequest().denyAll())
.httpBasic(Customizer.withDefaults());
return http.build();
}
}
Flowable Engage WebSocket Security Configuration
If you are creating a Flowable Engage application, then you need to add the following security configuration for the application.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.config.annotation.web.socket.EnableWebSocketSecurity;
import org.springframework.security.messaging.access.intercept.MessageMatcherDelegatingAuthorizationManager;
import org.springframework.security.messaging.web.csrf.CsrfChannelInterceptor;
import com.flowable.autoconfigure.security.FlowablePlatformSecurityProperties;
import com.flowable.engage.autoconfigure.websocket.WebSocketMessageBrokerProperties;
@Configuration(proxyBeanMethods = false)
@EnableWebSocketSecurity
public class WebSocketSecurityConfiguration {
@Bean
public AuthorizationManager<Message<?>> webSocketAuthorizationManager(MessageMatcherDelegatingAuthorizationManager.Builder messages,
WebSocketMessageBrokerProperties brokerProperties) {
// In case there are destination prefixes deny all of them as they are forwarded to the broker
String[] destinationPrefixes = brokerProperties.getDestinationPrefixes();
if (destinationPrefixes != null) {
for (String destinationPrefix : destinationPrefixes) {
messages.simpMessageDestMatchers(destinationPrefix + "/**").denyAll();
}
}
messages.anyMessage().authenticated();
return messages.build();
}
@Bean
public ChannelInterceptor csrfChannelInterceptor(FlowablePlatformSecurityProperties flowableSecurityProperties) {
if (flowableSecurityProperties.getRest().getCsrf().isEnabled()) {
return new CsrfChannelInterceptor();
}
return new ChannelInterceptor() {
};
}
}
User Definitions
Flowable applications can manage the features and permissions of an application used by definition user definitions.
User definitions follow a template pattern for each different type of user using the system. There are different patterns for administrators, operators, clients, etc. The user types also have different feature sets available: member groups, permissions, etc.
To define user definitions for a Flowable application, you need to create a file under:
src/main/resources/com/flowable/users/custom/<user-definitions>.user.json
Where <user-definitions> is a meaningful name for the set of user definitions.
The complete list of allowedFeatures are detailed in the following examples.
Example of Flowable Work User Definitions.
[
{
"key": "admin",
"name": "Flowable Administration User",
"allowedFeatures": [
"cases",
"changeContactPassword",
"changeOwnPassword",
"contacts",
"createUser",
"createWork",
"editContactAvatar",
"editOwnAvatar",
"processes",
"reports",
"reportsMetrics",
"tasks",
"templateManagement",
"work",
"actuators",
"user-mgmt"
]
}
]
Example of Flowable Engage User Definitions.
[
{
"key": "admin",
"name": "Flowable Administration User",
"allowedFeatures": [
"audioMessage",
"bubbles",
"cases",
"changeContactPassword",
"changeOwnPassword",
"clearMessage",
"contacts",
"createConversation",
"createUser",
"createWork",
"editContactAvatar",
"editConversationAvatar",
"editMessage",
"editOwnAvatar",
"emojiPicker",
"fileUpload",
"inputValidation",
"markdownInput",
"processes",
"reports",
"reportsMetrics",
"sendMessageFromProfile",
"slashActions",
"tasks",
"templateManagement",
"videoMessage",
"websockets",
"work",
"actuators",
"user-mgmt"
]
}
]
This table details which feature is available in each product and is associated with a short description of the use of that feature.
| allowedFeature | Work | Engage | Description |
|---|---|---|---|
| actuators | x | x | Grant access to Spring Boot actuators endpoints |
| audioMessage | x | Show icon to send an audio message | |
| bubbles | x | Enable message area view as bubbles | |
| changeContactPassword | x | x | Show a tab to change the user password |
| changeOwnPassword | x | x | Allows the user to change their own password from user settings |
| changeOwnTheme | x | x | Allows the user to change their own theme from user settings |
| clearMessage | x | Enables message toolbar with delete button to delete a sent message | |
| compliance | x | Enables the Compliance app | |
| confirmOnSave | x | x | Show confirmation alter when saving contact info in the contact details view |
| contacts | x | x | Enables the Contacts app |
| conversations | x | Enables the Conversations | |
| conversationSearch | x | Enable searching in a single conversation | |
| copyText | x | x | Allows copying the infos from the contact and license details view. In Engage it lets you to also copy info from slash actions in the conversation input |
| createConversation | x | Creating conversations allowed | |
| createUser | x | x | Creating users allowed |
| createWork | x | x | Starting workflows (cases / processes) allowed |
| deferPlatformUIBoot | x | x | Used to defer the Flowable UI boot, mostly used in custom.js where the developer can then manually boot the UI using wnd.flowable.boot() |
| deleteMessage | x | Allows the user to delete a message in a conversation | |
| deliveryStatus | x | Show message delivery status | |
| dashboards | x | x | Enables the Dashboards app |
| deployDesign | x | x | Allows the user to deploy applications from Design in Work through Work |
| disableDatatableFavorites | x | x | Disables favorites management in forms Datatable component |
| disableDefaultMarkdownListNumbering | x | Disables Markdown’s default behavior of sequential numbering in ordered lists, allowing custom numbering with gaps. v3.17.9+2025.1.02+ | |
| disableFormsDebug | x | x | Disables forms debugger, preventing the forms debugger to be shown programmatically |
| disableGeneralNewContactButton | x | x | Removes the create new contact button from the UI |
| disableGeneralNewConversationButton | x | x | Removes the create new conversation button from the UI |
| disableGeneralNewTaskButton | x | x | Removes the create new task button from the UI |
| disableGeneralNewWorkButton | x | x | Removes the create new instance button from the UI |
| disableGlobalNavigationBar | x | x | Removes the global navigation bar from the UI. 2025.1.01+ |
| disableGlobalNavigationSearch | x | x | Removes the global navigation search from the UI. 2025.1.01+ |
| disableGoToNextTask | x | x | Disables the navigation to the next task after completing a task |
| disableLockFocus | x | x | Allows the user to navigating outside the platform UI using keyboard |
| disableMessageMultiSelect | x | Disables multi selection of messages in a conversation | |
| disableTaskClaimConfirmation | x | x | Disables the confirmation dialog when claiming a task |
| displayMessageToolbar | x | Show the message toolbar | |
| documents | x | x | Enables the Documents app |
| editContactAvatar | x | x | Show a tab to modify the user avatar |
| editConversationAvatar | x | Allows changing the conversation image | |
| editConversationTitle | x | Allows the user to change the title of a conversation | |
| editCollapsibleSwitcher | x | x | Allows the user to change the title of a conversation |
| editMessage | x | Enables message toolbar with an edit button to modify a sent message | |
| editOwnAvatar | x | Allows the user to modify their own avatar from user settings | |
| emojiPicker | x | Show an icon to display an emoji panel | |
| enableCollapsibleSwitcher | x | x | Allows collapsing the left hand section of Work / Engage |
| enableCompleteOutcome | x | x | The complete button should always be enabled, even if the form is invalid |
| enableDesignIntegration | x | x | Enables the Design App in Work / Engage |
| enableFormAutoSave | x | x | Enables autosave for task forms |
| fileUpload | x | Show icon to upload a file | |
| forwardMessage | x | Enables the icon to forward a message | |
| hideFormSaveIndicator | x | x | When enableFormAutoSave is set, this can be enabled to hide the saving indicator |
| hideLanguage | x | x | Hides language selection tab from user settings |
| housekeeping | x | x | Allows users to access the housekeeping REST APIs |
| impersonateUser | x | x | Allows the user to impersonate another user (precondition: flowable.security.impersonate.allowed must be set to true) |
| inputValidation | x | Show an error tooltip when sending a message fails | |
| labs | x | x | Makes available a special route /labs in the frontend to toggle locally product features. Note that changing manually some of these features could lead into unexpected results, many of the features listed here are experimental and could change or be removed in subsequent releases |
| lastReadAvatars | x | Shows the avatar of the users that read a message | |
| licenseValidationInfo | x | x | Allows the user to access license validation information |
| login | x | x | Enables the Flowable login UI. Note: this if you are using OAuth2 you don't need to change anything for this feature |
| logout | x | x | Disables the logout menu from the user profile |
| markdownInput | x | Allows Markdown in messages | |
| mobileLogin | x | x | Show an extra tab in the user settings to display a QR code for login using the Flowable mobile app |
| opaqueNotifications | x | Do not display message contents in desktop notification, i.e. show "You have received a new message" instead of message preview | |
| personalAccessTokens | x | x | Allows users to creat their own personal access tokens for accessing the applications over REST (precondition: flowable.platform.idm.token-signing-secret must have a value set) |
| plainTextWithLinks | x | Render links in plain text messages, by default links are not displayed in plain text messages | |
| reactToMessage | x | Enables the icon to react to a message | |
| refreshTaskListOnComplete | x | x | Refresh the task list after completing a task |
| registerDevice | x | Allows the user to register a device | |
| replyToMessage | x | Enables the icon to reply to a message | |
| reports | x | x | Enables the Reports app and grants access to the reports-api |
| reportsMetrics | x | x | Enables the Metrics app |
| sendMessageFromProfile | x | Redirect Conversations chat from People tab or from the Contact details header | |
| sequenceValueManagement | x | x | Allows the user to manage sequence values over REST |
| showActualDateInfo | x | x | Display timestamps instead of relative time periods in the UI |
| showPdfWithAuth | x | x | Use regular url in pdf preview instead of using axios to fetch the data |
| slashActions | x | slash actions are allowed from the input message area | |
| snooze | x | Allows the user to mute the browser notification popup on new messages in the webapp | |
| tasks | x | x | Enables the Tasks app |
| templateManagement | x | x | Enables the Templates app |
| tenantDataInQueries | x | x | Allows users accessing all tenant data when using queries in Dashboards |
| themeManagement | x | x | Grant access to theme management |
| topNavigationBar | x | x | Renders a navigation bar at the top |
| useDownloadUrls | x | x | Use regular download links instead of using axios to download files |
| useNavigatorLanguage | x | x | Use browser selected language instead of the current user configured language |
| user-mgmt | x | x | Grant access to identity management |
| videoMessage | x | Show icon to send a video message | |
| websockets | x | x | Enables the use of websockets in the frontend or long polling as fallback if websockets are blocked. |
| work | x | x | Enables the Work app |
| workDesign | x | x | Grants access to Design through Work |
Changing manually some of these features could lead into unexpected results, many of the features listed here are experimental and could change or be removed in subsequent releases
Tenant Configuration
Flowable applications support different identity providers and authorization types.
Flowable provides an internal identity management (IDM) component that can manage tenants, users, groups, and privileges. The internal IDM component is populated with tenants, users, and groups defined in a tenant file. This file is read and loaded at the first boot of the application (if there are no existing users defined).
To define a tenant for a Flowable application you need to create a file under:
src/main/resources/com/flowable/tenant-setup/custom/<tenants>.json
where <tenants> is a meaningful name for the set of tenant definitions.
For example, the tenant JSON file for the demo tenant is named demo.json.
A tenantKey is defined in the file that is unique to this group of users for this tenant.
The tenant file looks like:
{
"name": "Flowable Demo",
"tenantKey": "demo",
"groups": [
{
"key": "flowableAdministrator",
"name": "Flowable Administrator"
},
{
"key": "flowableUser",
"name": "Flowable User"
}
],
"users": [
{
"firstName": "Flowable",
"lastName": "Admin",
"login": "admin",
"email": "admin@demo.flowable.io",
"language": "en",
"theme": "flowable",
"userDefinitionKey": "admin"
}
]
}
A tenant setup without tenantKey has all the users and groups created in the default tenant.
Database configuration
The project also requires the addition of properties for the database in the application properties file. The appropriate values for the following properties are required:
spring.datasource.url=
spring.datasource.username=
spring.datasource.password=
Infrastructure and Initial Startup
You now have a minimal setup with which you can run the application. However, before running the application, you need to set up the appropriate infrastructure for the Flowable Application.
License
A Flowable application also requires that you have
a valid license for the Product you are trying to access.
The license is either stored on the file system or in the database.
If the license is provided as a file, then it is
typically located in the .flowable folder of your home directory.
On Unix or macOS the file is ~/.flowable/flowable.license.
The location of the license file can be changed in the application.properties
file.
flowable.license.location=file:/myCustomLocation/flowable.license
To store the license in the database, then the following property must be set in
the applications.properties file:
flowable.license.db-store-enabled=true
With the license database store mode enabled a license is uploaded using any Flowable application.
Elasticsearch
Next, download Elasticsearch (any version in the 7.x line). You can download 7.10.0 from here.
Once the package is downloaded, you should expand it and then run it by executing bin/elasticsearch (bin\elasticsearch.bat on Windows).
By default, Elasticsearch runs in the foreground and prints the logs
in the console.
You can stop Elasticsearch by pressing Ctrl-C.
You can test that your Elasticsearch is running by sending an HTTP GET request to port 9200 on localhost (by going to http://localhost:9200/ in your browser).
More information about the Elasticsearch installation procedure is found at the official ElasticSearch setup guide.
Database
This depends on the database that you are using in your project.
ActiveMQ (Engage)
You only need this step if you are using Flowable Engage. If you are using Flowable Work you can skip this step.
You can download ActiveMQ 5.15.9 from here.
Once the package is downloaded, you can expand it and then run it by executing bin/activemq start (bin\activemq start on Windows).
ActiveMQ starts in the background.
You can stop the broker by executing bin/activemq stop (bin\activemq stop in Windows).
Alternatively, you can run bin/activemq console to have ActiveMQ run in the foreground (and stop it by doing a CTRL-C).
More information about the ActiveMQ 5.15.9 (latest stable version of the 5.15.x line at the time of writing this guide) installation procedure can be found in the office ActiveMQ setup guide.