{"id":322,"date":"2018-09-09T16:48:03","date_gmt":"2018-09-09T16:48:03","guid":{"rendered":"http:\/\/www.canchito-dev.com\/public\/blog\/?p=322"},"modified":"2021-05-02T13:46:23","modified_gmt":"2021-05-02T13:46:23","slug":"canchito-workflow-manager-cwm","status":"publish","type":"post","link":"http:\/\/www.canchito-dev.com\/public\/blog\/2018\/09\/09\/canchito-workflow-manager-cwm\/","title":{"rendered":"Canchito Workflow Manager (CWM)"},"content":{"rendered":"<div class=\"perfect-pullquote vcard pullquote-align-full pullquote-border-placement-left\"><blockquote><p><\/p>\n<p>Flowable BPM turned into a workflow manager with features such as file transfer via FTP and Samba, integration with Amazon Web Service, file transcodification and analysis using FFmpeg and MediaInfo, and more..<\/p>\n<p><\/p><\/blockquote><\/div>\n<div>\n  <a class=\"donate-with-crypto\"\n     href=\"https:\/\/commerce.coinbase.com\/checkout\/faf64f90-2e80-46ee-aeba-0fde14cbeb46\"><br \/>\n    Buy Me a Coffee<br \/>\n  <\/a><br \/>\n  <script src=\"https:\/\/commerce.coinbase.com\/v1\/checkout.js?version=201807\">\n  <\/script>\n<\/div>\n<section>\n<blockquote>\n<p class=\"text-justify\">Please note that this project is still under development<\/p>\n<\/blockquote>\n<\/section>\n<section id=\"introduction\" class=\"body-section\"><!-- introduction --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h1>Introduction<\/h1>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\"><strong>CANCHITO-WORKFLOW-MANAGER (CWM)<\/strong> is a powerful and yet lightweight and easy to use solution for handling workflows and business processes. At its core is a high performance open-source business process engine based on <a href=\"https:\/\/www.flowable.org\/\">Flowable<\/a> with the\u00a0flexibility and scalability to handle a wide variety of critical processes.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">We really hope that the additional features added to <a href=\"https:\/\/www.flowable.org\/\">Flowable<\/a> can be as beneficial as we hope they are.\u00a0If you would like to have a look into our other projects, please visit us at <a href=\"http:\/\/www.canchito-dev.com\">Canchito-Dev<\/a>.<\/p>\n<ul class=\"fa-ul list-docs\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#features\">Features<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#downloadAndContribute\">Download &amp; Contribute<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#sources\">Sources<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#license\">License<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#dears\">Dear haters, trolls, and everything-sucks-people<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#softwarerequirementspecifications\">Software Requirement Specifications<\/a><\/li>\n<\/ul>\n<\/section>\n<p><!-- introduction --><\/p>\n<section id=\"features\" class=\"body-section\"><!-- \"features\" --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Features<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<ul class=\"fa-ul list-docs\">\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Extremely simple, easy to understand<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Simple but clean structure<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Easy to scale<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Front- and Back-end are decoupled, allowing you to have them running in individual servers<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Commented code<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Integrates with a range of enterprise clouds, including Amazon Web Service, Microsoft Azure and Google Drive<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Integrates with FFmpeg and MediaInfo<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Custome palette perfectly compatible with Flowable Designer plug-in for Eclipse<\/li>\n<\/ul>\n<\/section>\n<p><!-- \"features\" --><\/p>\n<section id=\"downloadAndContribute\" class=\"body-section\"><!-- \"download\" --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Download &amp; Contribute<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Help us find bugs, add new features or simply just feel free to use it. Download <strong>CANCHITO-WORKFLOW-MANAGER (CWM)<\/strong> from our\u00a0<a href=\"https:\/\/github.com\/canchito-dev\/canchito-workflow-manager\">GitHub<\/a> site.<\/p>\n<p style=\"text-align: justify;\">If you would like to become an active contributor to this project please follow these simple steps:<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\n<li style=\"text-align: justify;\">Fork it<\/li>\n<li style=\"text-align: justify;\">Create your feature branch<\/li>\n<li style=\"text-align: justify;\">Commit your changes<\/li>\n<li style=\"text-align: justify;\">Push to the branch<\/li>\n<li style=\"text-align: justify;\">Create new Pull Request<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/section>\n<p><!-- \"download\" --><\/p>\n<section id=\"sources\" class=\"body-section\"><!-- sources --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Sources<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\">The source code can be found in our <a href=\"https:\/\/github.com\/canchito-dev\/canchito-workflow-manager\">\u00a0GitHub<\/a> site.<\/p>\n<ul class=\"fa-ul list-docs\">\n<li><i class=\"fa-li fa fa-folder\"><\/i><code>back-end<\/code>: has the source code for the back-end and is organized into several modules.<\/li>\n<li><i class=\"fa-li fa fa-folder\"><\/i><code>front-end<\/code>: has the source code for the fron-end<\/li>\n<li><i class=\"fa-li fa fa-folder\"><\/i><code>palette<\/code>: contains the source code for the Eclipse palette<\/li>\n<\/ul>\n<p class=\"text-justify\">Here is a detail explanation of the <code>back-end<\/code> modules:<\/p>\n<ul class=\"fa-ul list-docs\">\n<li><i class=\"fa-li fa fa-asterisk\"><\/i><code>cwm-app<\/code>: Main module. Has all the main resources and configurations<\/li>\n<li><i class=\"fa-li fa fa-asterisk\"><\/i><code>cwm-cloud<\/code>: Has all the implementations to use the different cloud services<\/li>\n<li><i class=\"fa-li fa fa-asterisk\"><\/i><code>cwm-core<\/code>: Handles CWM&#8217;s Async Job Executor<\/li>\n<li><i class=\"fa-li fa fa-asterisk\"><\/i><code>cwm-dao<\/code>: Handles all the database accesses. You can find all the repositories and entities here<\/li>\n<li><i class=\"fa-li fa fa-asterisk\"><\/i><code>cwm-flowable<\/code>: Implementations created for seamlessly integrate with <a href=\"https:\/\/www.flowable.org\/\">Flowable<\/a><\/li>\n<li><i class=\"fa-li fa fa-asterisk\"><\/i><code>cwm-rest-api<\/code>: Rest controllers for CWM<\/li>\n<li><i class=\"fa-li fa fa-asterisk\"><\/i><code>cwm-service<\/code>: Handles the business logic<\/li>\n<li><i class=\"fa-li fa fa-asterisk\"><\/i><code>cwm-cloud<\/code>: Contains all the task behaviors and runnables used in CWM&#8217;s Async Job Executor<\/li>\n<li><i class=\"fa-li fa fa-asterisk\"><\/i><code>cwm-utils<\/code>: Has all the app&#8217;s utils<\/li>\n<\/ul>\n<\/section>\n<p><!-- sources --><\/p>\n<section id=\"license\" class=\"body-section\"><!-- license --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>License<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">The MIT License (MIT)<\/p>\n<p style=\"text-align: justify;\">Copyright (c) 2017, canchito-dev<\/p>\n<p style=\"text-align: justify;\">Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files<br \/>\n(the \u201cSoftware\u201d), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge,<br \/>\npublish, distribute, sublicense, and\/or sell copies of the Software, and to permit persons to whom the Software is furnished to do<br \/>\nso, subject to the following conditions:<\/p>\n<p style=\"text-align: justify;\">The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.<\/p>\n<p style=\"text-align: justify;\">THE SOFTWARE IS PROVIDED \u201cAS IS\u201d, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br \/>\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE<br \/>\nFOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION<br \/>\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<\/p>\n<\/section>\n<p><!-- license --><\/p>\n<section id=\"dears\" class=\"body-section\"><!-- haters --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Dear haters, trolls and everything-sucks-people&#8230;<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">This project started as a way of helping me understand and learn about Flowable and Spring Boot. But it grew up to include some other features<br \/>\nthat have been helpful to me. It might not perfectly coded, but it was developed with all the good intensions at heart.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">This is a totally unpaid and voluntary project, developed during my free-time and shared on GitHub. It can be used for private or commercially,<br \/>\nwithout a cost. There is only one simple request, do not bash or complain. If you don&#8217;t like it, don&#8217;t use it.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">If you find an issue, please fill free and open a ticket, we will try to solve it as soon as possible. If you would like to become an active<br \/>\ncontributor to this project, even better.<\/p>\n<\/section>\n<p><!-- contribute --><\/p>\n<section id=\"softwarerequirementspecifications\" class=\"body-section\"><!-- softwarerequirementspecifications --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Software Requirement Specifications<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<ul class=\"fa-ul list-docs\">\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Decoupled front- and back-end, allowing them run in individual servers<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Integration with a range of enterprise clouds, including Amazon Web Service, Microsoft Azure and Google Drive<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Integration with MediaInfo<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Integration with FFmpeg<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Allow execution of long-running tasks<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>Prioritize process instances<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>File transferring by FTP and Samba<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i>High-available, redundant and scalable clustered platform<\/li>\n<\/ul>\n<\/section>\n<section id=\"theBpmEngine\" class=\"body-section\"><!-- theBpmEngine--><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h1>The BPM Engine<\/h1>\n<\/div>\n<ul class=\"fa-ul list-docs\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#whatisflowable\">What is Flowable?<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#currentlimitations\">Current &#8220;limitation&#8221;<\/a><\/li>\n<\/ul>\n<\/section>\n<section id=\"whatisflowable\" class=\"body-section\"><!-- whatisflowable --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>What is Flowable?<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\"><a href=\"https:\/\/www.flowable.org\/\">Flowable<\/a> is a light-weight workflow and Business Process Management (BPM) Platform targeted at business people,\u00a0developers and system admins. Its core is a super-fast and rock-solid BPMN 2 process engine for Java. It&#8217;s open-source and distributed under the Apache\u00a0license. <a href=\"https:\/\/www.flowable.org\/\">Flowable<\/a> runs in any Java application, on a server, on a cluster or in the cloud. It integrates perfectly\u00a0with Spring, it is extremely lightweight and based on simple concepts. Flowable is a fork of <a href=\"https:\/\/www.activiti.org\/\">Activiti<\/a> (registered\u00a0trademark of <a href=\"https:\/\/www.alfresco.com\/\">Alfresco<\/a>).<\/p>\n<\/section>\n<p><!-- whatisflowable --><\/p>\n<section id=\"currentlimitations\" class=\"body-section\"><!-- \"currentlimitations\" --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Current &#8220;limitation&#8221;<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">In order to understand the main <i>&#8220;limitation&#8221;<\/i>, you need to understand how Flowable&#8217;s asyc job executor works. Please read the following section from\u00a0Flowable&#8217;s user guide:<\/p>\n<ul class=\"fa-ul list-docs\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"http:\/\/www.flowable.org\/docs\/userguide\/index.html#jobExecutorConfiguration\">3.9. Job Executor (from version 6.0.0 onwards)<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"http:\/\/www.flowable.org\/docs\/userguide\/index.html#_job_executor_activation\">3.10. Job executor activation<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"http:\/\/www.flowable.org\/docs\/userguide\/index.html#_async_executor\">18.1. Async Executor<\/a><\/li>\n<\/ul>\n<p class=\"text-justify\" style=\"text-align: justify;\">And according to Frederik Heremans (one of Flowable&#8217;s main developers), in his reply to this<br \/>\n<a href=\"https:\/\/community.alfresco.com\/thread\/220468-modelling-an-async-user-wait-on-a-long-running-service-task\">question<\/a> rised in Flowable&#8217;s\u00a0official forum, we also know that when executing long-running tasks the async job executor, behaves as follow:<\/p>\n<ul class=\"fa-ul list-docs\" style=\"text-align: justify;\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i>Executing a service-task (or any other task) keeps a transaction open until a wait-state\/process-end\/async-task\u00a0is reached. If you have long-running operations, make sure your database doesn&#8217;t time out<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i>When a jobs is running for 5 minutes, the job aquisistion-thread assumes the async job executor that was running\u00a0the job, has either died or has failed. The lock of the job is removed and the job will be executed by another thread in the executor-pool. This timeout-setting\u00a0can be raised, if that is required<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i>Long-running tasks modeled in the flowable-process always keep a transaction open and a async job executor thread\u00a0occupied. Better practice is to use a queue-signal approach where the long-running operation is executed outside of Flowable (queued to eg. camel using a\u00a0service-task, providing the neccesary variables needed alongside). When the long-running task is completed, it should signal the execution, which has a\u00a0recieve-task modeled in<\/li>\n<\/ul>\n<p class=\"text-justify\" style=\"text-align: justify;\">How the async job executor behaves with the long-running task is considered as a <i>&#8220;limitation&#8221;<\/i>, because of <strong>CWM<\/strong>&#8216;s software\u00a0requirements. But they are actually not limitations. <strong>CWM<\/strong> simply requires a different behavior for them. To solve this, <strong>CWM<\/strong>\u00a0implements its own async job executor. Please visit section <a href=\"#asyncjobexecutor\">Async Job Executor<\/a>.<\/p>\n<\/section>\n<p><!-- \"currentlimitations\" --><\/p>\n<section id=\"theBpmEngine\" class=\"body-section\"><!-- theBpmEngine--><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h1>The BPM Engine<\/h1>\n<\/div>\n<ul class=\"fa-ul list-docs\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#requiredsoftware\">Required Software<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#definitions\">Definitions<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#configurationandsetup\">Configuration &amp; Setup<\/a><\/li>\n<\/ul>\n<\/section>\n<section id=\"requiredsoftware\" class=\"body-section\"><!-- requiredsoftware --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Required Software<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">For the front-end, you need a standard Web server with at least:<\/p>\n<ul class=\"fa-ul list-docs\" style=\"text-align: justify;\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i>PHP 5.3.2 or higher<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i>Make sure <em>mod_rewrite<\/em> is enabled and activated<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i>Basic knowledge of Composer<\/li>\n<\/ul>\n<p class=\"text-justify\" style=\"text-align: justify;\">For your development environment, you can use <a href=\"http:\/\/www.wampserver.com\/en\/\">WAMPServer<\/a>, which is a Windows web\u00a0development environment, and stands for <strong>W<\/strong>indows, <strong>A<\/strong>pache, <strong>M<\/strong>ySQL and\u00a0<strong>PHP<\/strong>.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Composer is a very simple and easy to use dependency manager for PHP. It allows you to declare the libraries your project\u00a0depends on and it will manage (install\/update) them for you. You can download the Windows installer from their official\u00a0<a href=\"https:\/\/getcomposer.org\/download\/\">site<\/a>.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Now, the back-end runs on a JDK higher than or equal to version 7. Go to <a href=\"http:\/\/www.oracle.com\/technetwork\/java\/javase\/downloads\/jdk8-downloads-2133151.html\">Oracle Java SE site<\/a>\u00a0and download it. There are installation instructions on that page as well.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">In order to make sure that the installation was successful, run java -version on the command line. That should print the\u00a0installed version of your JDK:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"msdos\">C:&gt;java\u00a0-version\r\njava\u00a0version\u00a0\"1.8.0_141\"\r\nJava(TM)\u00a0SE\u00a0Runtime\u00a0Environment\u00a0(build\u00a01.8.0_141-b15)\r\nJava\u00a0HotSpot(TM)\u00a064-Bit\u00a0Server\u00a0VM\u00a0(build\u00a025.141-b15,\u00a0mixed\u00a0mode)<\/pre>\n<p class=\"text-justify\" style=\"text-align: justify;\">Finally, you need a MySQL database. If you used <a href=\"http:\/\/www.wampserver.com\/en\/\">WAMPServer<\/a>, it should automatically\u00a0be installed.<\/p>\n<\/section>\n<p><!-- requiredsoftware --><\/p>\n<section id=\"definitions\" class=\"body-section\"><!-- definitions --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Definitions<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<ul class=\"fa-ul list-docs\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#definitionfolderhandler\">What are Folder Handlers?<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#definitionfilehandler\">What are File Handlers?<\/a><\/li>\n<\/ul>\n<\/section>\n<p><!-- definitions --><\/p>\n<section id=\"definitionfolderhandler\" class=\"body-section\"><!-- definitionfolderhandler --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h3>What are Folder Handlers?<\/h3>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">A folder handler is a tag or an alternative name for referencing an actual directory in a FTP or Samba network location, a local storage or even\u00a0one in one of the supported clouds. They are used for describing actual paths and how to access them. Folder handlers simplify how you refer to\u00a0directories, as you only specify a short and descriptive name, instead of a complex and longer path plus file name.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Moreover, folder handler&#8217; path and credentials only need to be updated once, and automatically, all actions using that folder will be updated.<\/p>\n<\/section>\n<p><!-- definitionfolderhandler --><\/p>\n<section id=\"definitionfilehandler\" class=\"body-section\"><!-- definitionfilehandler --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h3>What are File Handlers?<\/h3>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">A file handler is used as a tag for referencing a file within a workflow. Thanks to file handlers, you do not need to use the full path and name\u00a0of each file in every step of a workflow. Consequently, it is only necessary to assign a file handler to a file, and CWM associates the full path\u00a0and file name of the actual file during each step of the workflow.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">It is required that each file is associated to a unique file handler. If the same file handler is used for a second file, the first values are\u00a0overwritten.<\/p>\n<\/section>\n<p><!-- definitionfilehandler --><\/p>\n<section id=\"configurationandsetup\" class=\"body-section\"><!-- configurationandsetup --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Configuration and Setup<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<ul class=\"fa-ul list-docs\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#dbsetup\">Database Setup<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#frontendsetup\">Front-End Setup<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#backendsetup\">Back-End Setup<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#mailconfiguration\">Mail Configuration<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#cloudconfiguration\">Cloud Configuration<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#dbConfiguration\">Database Configuration<\/a><\/li>\n<\/ul>\n<\/section>\n<p><!-- configurationandsetup --><\/p>\n<section id=\"dbsetup\" class=\"body-section\"><!-- dbsetup --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h3>Database Setup<\/h3>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Create the database schema and all the database tables. Simply execute the <em>.sql<\/em> statements in the\u00a0<code>database<\/code>&#8211; folder (with <a href=\"https:\/\/www.phpmyadmin.net\/\">PHPMyAdmin<\/a> for example).<\/p>\n<\/section>\n<p><!-- dbsetup --><\/p>\n<section id=\"frontendsetup\" class=\"body-section\"><!-- frontendsetup --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h3>Front-End Setup<\/h3>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Copy the content of the <code>front-end<\/code>&#8211; folder into the Web server default folder and just follow these steps:<\/p>\n<ol class=\"list-docs\">\n<li style=\"text-align: justify;\">Make sure you have <em>mod_rewrite<\/em> activated on your server \/ in your environment.<\/li>\n<li style=\"text-align: justify;\">Install Composer and run <code>composer install<\/code> in the project&#8217;s folder to download the dependencies and create the\u00a0autoloading stuff from Composer automatically. For those who are not familiar with Composer, just remember back in the days,\u00a0when you were using a PHP files with all the includes you needed. Well, Composer creates classes that automatically do this.<\/li>\n<li style=\"text-align: justify;\">Create a virtual host. For instance <code>cwm.canchito-dev.com<\/code>.<\/li>\n<li style=\"text-align: justify;\">Go to folder <code>application\/config<\/code> and open the file <code>config.php<\/code>. Here you will have to modify some parameters.<\/li>\n<\/ol>\n<ul class=\"list-docs\">\n<li style=\"text-align: justify;\"><code>TENANT_ID_PART<\/code>:<br \/>\nConfiguration for specifying which part of the <code>$_SERVER['HTTP_HOST']<\/code> variable use as a tenant id. For instance:<br \/>\n<code>$_SERVER['HTTP_HOST'] = cwm.canchito-dev.com<\/code>. The system splits &#8216;nahual.domain&#8217; by the &#8216;.&#8217; into two substrings<br \/>\nIf TENANT_ID_PART = 0, &#8216;cwm&#8217; will be used as TENANT_ID<br \/>\nIf TENANT_ID_PART = 1, &#8216;canchito-dev&#8217; will be used as TENANT_ID and so on<\/li>\n<li style=\"text-align: justify;\"><code>CWM_URL_DOMAIN<\/code>: the domain where the back-end is running<\/li>\n<li style=\"text-align: justify;\"><code>CWM_URL_PORT<\/code>: the port in which the back-end is listening<\/li>\n<li style=\"text-align: justify;\"><code>CWM_URL_SUB_FOLDER<\/code>: the path of the main dispatcher servlet<\/li>\n<\/ul>\n<\/section>\n<p><!-- frontendsetup --><\/p>\n<section id=\"backendsetup\" class=\"body-section\"><!-- backendsetup --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h3>Back-End Setup<\/h3>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Open the configuration file <code>src\/main\/resources\/application.properties<\/code> and modify:<\/p>\n<ul class=\"fa-ul list-docs\" style=\"text-align: justify;\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>server.address<\/code>: Network address to which the server should bind to<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>server.connection-timeout<\/code>: Time in milliseconds that connectors will wait for another HTTP request\u00a0before closing the connection. When not set, the connector&#8217;s container-specific default will be used. Use a value of -1 to indicate no\u00a0(i.e. infinite) timeout<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>server.display-name<\/code>: Display name of the application<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>server.servlet-path<\/code>: Path of the main dispatcher servlet<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>server.port<\/code>: Server HTTP port<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>server.tomcat.max-connections<\/code>: Maximum number of connections that the server will accept and process\u00a0at any given time<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>server.tomcat.max-threads<\/code>: Maximum amount of worker threads<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>server.tomcat.uri-encodin<\/code>: Character encoding to use to decode the URI<\/li>\n<\/ul>\n<p class=\"text-justify\" style=\"text-align: justify;\">For instance:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">server.address=localhost\r\nserver.connection-timeout=60000\r\nserver.display-name=Canchito Workflow Manager\r\nserver.servlet-path=\/canchito-dev-rest\r\nserver.port=10000\r\nserver.tomcat.max-connections=100\r\nserver.tomcat.max-threads=100\r\nserver.tomcat.uri-encoding=UTF-8<\/pre>\n<\/section>\n<p><!-- backendsetup --><\/p>\n<section id=\"mailconfiguration\" class=\"body-main\"><!-- mailconfiguration --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h3>Mail Configuration<\/h3>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Mails can be sent from both the front- and the back-end. Let&#8217;s first do the configuration for the front-ent by opening the\u00a0<code>application\/config\/config.php<\/code> file and modifying the following parameter to suit your needs:<\/p>\n<ul class=\"fa-ul list-docs\" style=\"text-align: justify;\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>IS_SMTP<\/code>: Tells PHPMailer to use SMTP<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>MAIL_SERVER<\/code>: Sets the hostname of the mail server<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>SMTP_PORT<\/code>: Sets the SMTP port number &#8211; 587 for authenticated TLS, a.k.a. RFC4409 SMTP submission<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>SMTP_USERNAME<\/code>: Username to use for SMTP authentication &#8211; use full email address for gmail<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>SMTP_PWD<\/code>: Password to use for SMTP authentication<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>SMTP_DEBUG<\/code>: Enable SMTP debugging: (0) = off (for production use); (1) = client messages;<br \/>\n(2) = client and server messages. Default is 0<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>SMTP_SECURE<\/code>: Set the encryption system to use &#8211; ssl (deprecated) or tls. Default is tls<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>SMTP_AUTH<\/code>: Whether to use SMTP authentication. Default is true<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>MAIL_CHARSET<\/code>: Sets the character set<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>DEBUG_OUTPUT<\/code>: Ask for HTML-friendly debug output. Default is html<\/li>\n<\/ul>\n<p class=\"text-justify\" style=\"text-align: justify;\">Now, the mail configuration for the back-end is needed so that <a href=\"https:\/\/www.flowable.org\/\">Flowable<\/a> can send mails\u00a0by its mail task. To configure it, open the file <code>src\/main\/resources\/application.properties<\/code> and modify the following\u00a0fields:<\/p>\n<ul class=\"fa-ul list-docs\">\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i><code>flowable.mail-server-default-from<\/code>: The name of the sender as it will appear in mail<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i><code>flowable.mail-server-host<\/code>: SMTP server host. For instance `smtp.example.com`<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i><code>flowable.mail-server-password<\/code>: Login password of the SMTP server<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i><code>flowable.mail-server-port<\/code>: SMTP server port<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i><code>flowable.mail-server-use-tls<\/code>: Use tls or not<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i><code>flowable.mail-server-user-name<\/code>: Login user of the SMTP server<\/li>\n<\/ul>\n<\/section>\n<p><!-- mailconfiguration --><\/p>\n<section id=\"cloudconfiguration\" class=\"body-main\"><!-- cloudconfiguration --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h3>Cloud Configuration<\/h3>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">At the moment, the system can integrate with Amazon Web Services (AWS), but the roadmap includes integration with other clouds such as Microsoft&#8217;s Azure and\u00a0Google. For any cloud, it is required a valid account. To obtain a free AWS account, go to the <a href=\"https:\/\/aws.amazon.com\/free\/\">AWS Free Tier home page<\/a>\u00a0and click <i>Create A Free Account\/Create an AWS Account<\/i>. Signing up will enable you to use all of the services offered by AWS.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">To configure it, open the file <code>src\/main\/resources\/application.properties<\/code> and modify the following fields:<\/p>\n<ul class=\"fa-ul list-docs\">\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i><code>amazon.credentials-access-key-id<\/code>: The access key of the account<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i><code>amazon.credentials-secret-access-key<\/code>: The secret access key related to the account<\/li>\n<li style=\"text-align: justify;\"><i class=\"fa-li fa fa-check-square\"><\/i><code>amazon.configuration-region<\/code>: The region to which the account should log in<\/li>\n<\/ul>\n<\/section>\n<p><!-- cloudconfiguration --><\/p>\n<section id=\"dbConfiguration\" class=\"body-main\"><!-- dbConfiguration --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h3>Database Configuration<\/h3>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">The database configuration is done in the <code>src\/main\/resources\/application.properties<\/code> file. Simply, modify the following\u00a0parameter to suit your needs:<\/p>\n<ul class=\"fa-ul list-docs\" style=\"text-align: justify;\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>spring.datasource.continue-on-error<\/code>: Do not stop if an error occurs while initializing the database<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>spring.datasource.driver-class-name<\/code>: Fully qualified name of the JDBC driver. Auto-detected based on the URL by default<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>spring.datasource.password<\/code>: Login password of the databaser<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>spring.datasource.url<\/code>: JDBC url of the database<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>spring.datasource.username<\/code>: Login username of the database<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>cwm.datasource.*<\/code>: Datasource specific settings<\/li>\n<\/ul>\n<p class=\"text-justify\" style=\"text-align: justify;\">For instance:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">spring.datasource.continue-on-error=false\r\nspring.datasource.url=jdbc:mysql:\/\/localhost:3306\/database?autoReconnect=true\r\nspring.datasource.username=username\r\nspring.datasource.password=password\r\nspring.datasource.driver-class-name=com.mysql.jdbc.Driver\r\ncwm.datasource.test-on-borrow=true\r\ncwm.datasource.test-on-return=true\r\ncwm.datasource.test-while-idle=true\r\ncwm.datasource.validation-query=SELECT 1\r\ncwm.datasource.validation-interval=30000\r\ncwm.datasource.connection-timeout=60000\r\ncwm.datasource.connection-test-query=SELECT 1\r\ncwm.datasource.log-validation-errors=true\r\ncwm.datasource.max-idle=1\r\ncwm.datasource.min-idle=1\r\ncwm.datasource.max-active=5\r\ncwm.datasource.initial-size=5\r\ncwm.datasource.time-between-eviction-runs-millis=5000\r\ncwm.datasource.min-evictable-idle-time-millis=30000<\/pre>\n<\/section>\n<p><!-- dbConfiguration --><\/p>\n<section id=\"cwmAsyncExecutor\" class=\"body-section\"><!-- cwmAsyncExecutor --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h1>CWM&#8217;s Async Executor<\/h1>\n<\/div>\n<ul class=\"fa-ul list-docs\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#asyncjobexecutor\">Async Job Executor<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#asyncjobexecutordesign\">Async Executor&#8217;s Design<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#asyncjobexecutorconfiguration\">Async Executor&#8217;s Configuration<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"#createlongrunningservicetask\">Creating a long-running Service Task<\/a><\/li>\n<\/ul>\n<\/section>\n<p><!-- cwmAsyncExecutor --><\/p>\n<section id=\"asyncjobexecutor\" class=\"body-section\"><!-- asyncjobexecuto --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Async Job Executor<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Put in simple words, <a href=\"https:\/\/github.com\/canchito-dev\/canchito-workflow-manager\"><strong>CANCHITO-WORKFLOW-MANAGER (CWM)<\/strong><\/a>&#8216;s\u00a0async job executor are individual threads that are started once when the application is started. Each thread starts a thread pool that reuses a\u00a0(configurable) fixed number of threads operating off database table called\u00a0<em>CWM_TASKS_QUEUE<\/em>\u00a0and acting as a priority blocking list, using\u00a0the provided ThreadFactory to create new threads when needed. At any point, at most\u00a0<em>n<\/em>\u00a0threads will be active processing tasks.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"330\" data-permalink=\"http:\/\/www.canchito-dev.com\/public\/blog\/2018\/09\/09\/canchito-workflow-manager-cwm\/canchito_dev_task_queue_service\/\" data-orig-file=\"http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_task_queue_service.png\" data-orig-size=\"409,386\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"canchito_dev_task_queue_service\" data-image-description=\"&lt;p&gt;CANCHITO-DEV: Task Queue Service&lt;\/p&gt;\n\" data-image-caption=\"\" data-large-file=\"http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_task_queue_service.png\" class=\"aligncenter wp-image-330 size-full\" title=\"CANCHITO-DEV: Task Queue Service\" src=\"http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_task_queue_service.png\" alt=\"CANCHITO-DEV: Task Queue Service\" width=\"409\" height=\"386\" srcset=\"http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_task_queue_service.png 409w, http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_task_queue_service-300x283.png 300w\" sizes=\"auto, (max-width: 409px) 100vw, 409px\" \/><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Periodically, pending tasks are pulled from the database. The number of pending tasks that are pulled at once, depends on the number of available\u00a0threads on <a href=\"https:\/\/github.com\/canchito-dev\/canchito-workflow-manager\"><strong>CANCHITO-WORKFLOW-MANAGER (CWM)<\/strong><\/a>&#8216;s async job\u00a0executor for a specific task type. If additional tasks are submitted when all threads are active, they will reside in the database until a thread\u00a0is available.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">If any thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.\u00a0The threads in the pool will exist until it is explicitly shutdown.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Once a task is pulled by a thread, it is locked. By locking it, we can have several <a href=\"https:\/\/github.com\/canchito-dev\/canchito-workflow-manager\"><strong>CANCHITO-WORKFLOW-MANAGER (CWM)<\/strong><\/a>\u00a0simultaneously running on different servers. Thus allowing us to have a failover, clustered system.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">If two or more <a href=\"https:\/\/github.com\/canchito-dev\/canchito-workflow-manager\"><strong>CANCHITO-WORKFLOW-MANAGER (CWM)<\/strong><\/a>&#8216;s async job\u00a0executor are started, they all will be raising for pulling the pending tasks. Consequently, only the first one that looks the task, will be the one\u00a0that will execute it. The other async job executor will get an optimistic locking exception.<\/p>\n<\/section>\n<p><!-- asyncjobexecuto --><\/p>\n<section id=\"asyncjobexecutordesign\" class=\"body-section\"><!-- asyncjobexecutordesign --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Async Executor&#8217;s Design<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">In order to understand the way long-running tasks are added to the queue, lets have a look at a very simple workflow as the one in the below image.\u00a0As you can see, it is composed of a start event, a copy task (which is a service task), and an end event.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"329\" data-permalink=\"http:\/\/www.canchito-dev.com\/public\/blog\/2018\/09\/09\/canchito-workflow-manager-cwm\/canchito_dev_copy_task_sample_workflow\/\" data-orig-file=\"http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_copy_task_sample_workflow.png\" data-orig-size=\"300,93\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"canchito_dev_copy_task_sample_workflow\" data-image-description=\"&lt;p&gt;CANCHITO-DEV: Copy Task Sample Workflow&lt;\/p&gt;\n\" data-image-caption=\"\" data-large-file=\"http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_copy_task_sample_workflow.png\" class=\"aligncenter size-full wp-image-329\" src=\"http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_copy_task_sample_workflow.png\" alt=\"CANCHITO-DEV: Copy Task Sample Workflow\" width=\"300\" height=\"93\" \/><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">The copy task is a long-running service task, which needs to be processed by the async job executor. Long-runing tasks in <a href=\"https:\/\/github.com\/canchito-dev\/canchito-workflow-manager\"><strong>CANCHITO-WORKFLOW-MANAGER (CWM)<\/strong><\/a>\u00a0extend\u00a0<em>AbstractTaskCanchitoBehavior<\/em>, which at the same time extend from\u00a0<a href=\"https:\/\/www.flowable.org\/\" rel=\"nofollow\">Flowable<\/a>&#8216;s<br \/>\n<em>TriggerableActivityBehavior<\/em> class.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">The <em>TriggerableActivityBehavior<\/em>\u00a0is the parent class\u00a0for many BPMN 2.0 task types such as ReceiveTask, ScriptTask, UserTask, etc. This class\u00a0provides two methods:\u00a0 <code>execute()<\/code>and\u00a0<code>trigger()<\/code>.\u00a0These four methods are the pillars for creating a long-running task\u00a0implementing the\u00a0<em>TriggerableActivityBehavior<\/em>\u00a0instead of adding two BPMN task (send task and receive task) in your process diagram.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">The class\u00a0<em>AbstractTaskCanchitoBehavior<\/em> provides a two methods:\u00a0<code>submitTask()<\/code> and <code>checkSignal(DelegateExecution execution)<\/code>.\u00a0These four methods are the pillars for creating a long-running task\u00a0implementing the <em>TriggerableActivityBehavior<\/em>\u00a0instead of adding two BPMN task (send task and receive task) in your process diagram.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"328\" data-permalink=\"http:\/\/www.canchito-dev.com\/public\/blog\/2018\/09\/09\/canchito-workflow-manager-cwm\/canchito_dev_async_executor_design\/\" data-orig-file=\"http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_async_executor_design.png\" data-orig-size=\"852,492\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"canchito_dev_async_executor_design\" data-image-description=\"&lt;p&gt;CANCHITO-DEV: Async Executor&amp;#8217;s Design&lt;\/p&gt;\n\" data-image-caption=\"\" data-large-file=\"http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_async_executor_design.png\" class=\"aligncenter size-full wp-image-328\" src=\"http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_async_executor_design.png\" alt=\"CANCHITO-DEV: Async Executor's Design\" width=\"852\" height=\"492\" srcset=\"http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_async_executor_design.png 852w, http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_async_executor_design-300x173.png 300w, http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_async_executor_design-768x443.png 768w, http:\/\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2018\/09\/canchito_dev_async_executor_design-624x360.png 624w\" sizes=\"auto, (max-width: 852px) 100vw, 852px\" \/><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">The\u00a0<code>execute(DelegateExecution execution)<\/code>\u00a0method is invoked when the service task is entered. In our case, it is typically used for data\u00a0validation and preparation. There is no business logic here. For instance, it validates that all the needed information for the task to be correctly\u00a0executed has valid values.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">The <code>submitTask(DelegateExecution execution, JSONObject details, String beanId)<\/code>\u00a0method submits an asynchronous task to the actual service.\u00a0The submit action is actually storing the task in the database table by calling the <code>save()<\/code> method from the <em>GenericTaskService<\/em> class.\u00a0You can modify this method according to your database table structure.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">After submitting the task and the method returns, the process engine will\u00a0<strong>not<\/strong>\u00a0continue execution. The <em>TriggerableActivityBehavior<\/em>\u00a0acts as a wait state. This means, that the process instances is put on hold, until a trigger is received.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Periodically, the <em>AcquireTaskThread<\/em> in charge of these kind of service task (in this example, the copy task), read the task que database table.\u00a0When it finds a new task, it acquires it, and locks it. Once locked, it calls the <code>run()<\/code> method. Here, you will find the business logic for\u00a0the invoked service task. For our examples, it will problably call functions and method to copy a file from one location to another. When done,\u00a0<em>AcquireTaskThread<\/em> will call the <code>trigger()<\/code> method.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">The\u00a0<code>trigger(DelegateExecution execution, String signalName, Object signalData)<\/code>\u00a0method is invoked as the process engine is being triggered\u00a0by the callback. The\u00a0<code>trigger()<\/code>\u00a0method is responsible for leaving the service task activity and allowing the normal flow of the process instance.\u00a0But before leaving the service task, the <code>checkSignal()<\/code> is called. It is in this method, were the execution of the service task&#8217;s logic is\u00a0analyzed and determined if it finished correctly or with errors.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">By having a separate thread pool for executing long-running tasks, <a href=\"https:\/\/github.com\/canchito-dev\/canchito-workflow-manager\"><strong>CANCHITO-WORKFLOW-MANAGER (CWM)<\/strong><\/a>\u00a0has decoupled the process engine from the service implementation. From the point of view of\u00a0<a href=\"https:\/\/www.flowable.org\/\" rel=\"nofollow\">Flowable<\/a>&#8216;s\u00a0process engine, the <em>TriggerableActivityBehavior<\/em>\u00a0is a wait state: after the\u00a0<code>execute()<\/code>\u00a0method returns, the process engine will stop execution,\u00a0makes the state of the execution to the database persistence and wait for the callback to occur.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">As the long-running task implementation is not directly executed by\u00a0<a href=\"https:\/\/www.flowable.org\/\" rel=\"nofollow\">Flowable<\/a>&#8216;s process engine and\u00a0it does not participate in the process engine transaction, if there is an error in the service implementation, the failure will not cause the process\u00a0engine to roll back.<\/p>\n<\/section>\n<p><!-- asyncjobexecutordesign --><\/p>\n<section id=\"asyncjobexecutorconfiguration\" class=\"body-section\"><!-- asyncjobexecutorconfiguration --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Async Executor&#8217;s Configuration<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">The async job executor configuration is done by modifying two XML files (found under <code>src\/main\/resources\/<\/code>):<\/p>\n<ul class=\"fa-ul list-docs\" style=\"text-align: justify;\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>task-queue-beans.xml<\/code>: specified how each CWM&#8217;s async job executor, dedicated to process a specific task is configured<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>task-runnable-beans.xml<\/code>: here you will find the runnable classes that are used by each CWM&#8217;s async job executor to execute the task<\/li>\n<\/ul>\n<p class=\"text-justify\" style=\"text-align: justify;\">As you can see, each queue used by the CWM&#8217;s async job executor needs to have some configuration. Let&#8217;s describe those parameters found in <code>task-queue-beans.xml<\/code> file.<\/p>\n<ul class=\"fa-ul list-docs\" style=\"text-align: justify;\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>runnableName<\/code>: the id of the runnable that and instance is initialized and afterward executed. This is the id which relates to the information\u00a0found in <code>task-runnable-beans.xml<\/code>.<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>poolName<\/code>: the name of the thread pool<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>corePoolSize<\/code>: the number of threads to keep in the pool, even if they are idle<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>maximumPoolSize<\/code>: the maximum number of threads to allow in the pool<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>keepAliveTimeInMillis<\/code>: when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks\u00a0before terminating<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>acquireWaitTimeInMillis<\/code>: millis to wait before new tasks are pulled from the database<\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><code>maxTasksPerAcquisition<\/code>: maximum tasks that can be pulled from the database<\/li>\n<\/ul>\n<p class=\"text-justify\" style=\"text-align: justify;\">For instance <code>task-runnable-beans.xml<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"xml\">&lt;bean\u00a0id=\"task1Runnable\"\u00a0class=\"com.canchitodev.cwm.tasks.runnable.Task1Runnable\"\u00a0scope=\"prototype\"&gt;&lt;\/bean&gt;<\/pre>\n<p class=\"text-justify\">For instance <code>task-queue-beans.xml<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"xml\">&lt;bean\u00a0id=\"task1Queue\"\u00a0class=\"com.canchitodev.cwm.threadpool.service.TaskQueue\"\u00a0scope=\"prototype\"&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0&lt;property\u00a0name=\"runnableName\"\u00a0value=\"task1Runnable\"\u00a0\/&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0&lt;property\u00a0name=\"poolName\"\u00a0value=\"task1Queue\"\u00a0\/&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0&lt;property\u00a0name=\"corePoolSize\"\u00a0value=\"2\"\u00a0\/&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0&lt;property\u00a0name=\"maximumPoolSize\"\u00a0value=\"5\"\u00a0\/&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0&lt;property\u00a0name=\"keepAliveTimeInMillis\"\u00a0value=\"300000\"\/&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0&lt;property\u00a0name=\"acquireWaitTimeInMillis\"\u00a0value=\"5000\"\/&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0&lt;property\u00a0name=\"maxTasksPerAcquisition\"\u00a0value=\"2\"\/&gt;\r\n&lt;\/bean&gt;<\/pre>\n<\/section>\n<p><!-- asyncjobexecutorconfiguration --><\/p>\n<section id=\"createlongrunningservicetask\" class=\"body-section\"><!-- createlongrunningservicetask --><\/p>\n<div class=\"page-header-doc\">\n<p><!-- page-header-doc --><\/p>\n<h2>Creating a long-running Service Task<\/h2>\n<\/div>\n<p><!-- page-header-doc --><\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">A long-running service task is composed of two different classes: <em>Behavior<\/em> class and <em>Runnable<\/em> class.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">The behavior class, extends from\u00a0<em>AbstractTaskCanchitoBehavior<\/em>, which at the same time extend from\u00a0<a href=\"https:\/\/www.flowable.org\/\" rel=\"nofollow\">Flowable<\/a>&#8216;s\u00a0<em>TaskActivityBehavior<\/em> class. Let&#8217;s have a look at how to implement it by creating a new class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">@Service(\"task1\")\r\n@Scope(\"prototype\")\r\npublic\u00a0class\u00a0Task1Behavior\u00a0extends\u00a0AbstractTaskCanchitoBehavior\u00a0{\r\n\u00a0\u00a0private\u00a0static\u00a0final\u00a0long\u00a0serialVersionUID\u00a0=\u00a0-4740654158860004620L;\r\n\r\n\u00a0\u00a0@Override\r\n\u00a0\u00a0public\u00a0void\u00a0execute(DelegateExecution\u00a0execution)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0try\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.submitTask(execution,\u00a0new\u00a0JSONObject(),\u00a0\"task1Runnable\");\r\n\u00a0\u00a0\u00a0\u00a0}\u00a0catch\u00a0(Exception\u00a0e)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.throwException(execution,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"There\u00a0was\u00a0a\u00a0problem\u00a0when\u00a0trying\u00a0to\u00a0execute\u00a0task\u00a0'task1Runnable'\"\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0}\r\n\r\n\u00a0\u00a0@Override\r\n\u00a0\u00a0protected\u00a0void\u00a0validateParameters(DelegateExecution\u00a0execution)\u00a0throws\u00a0IllegalArgumentException\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\/\/\u00a0TODO\u00a0Auto-generated\u00a0method\u00a0stub\r\n\u00a0\u00a0}\r\n}<\/pre>\n<p>You can add additional logic before calling the <code>submitTask()<\/code> method if required. For our example, this would be enough.<\/p>\n<p class=\"text-justify\" style=\"text-align: justify;\">Next, create the <em>Runnable<\/em> class. Remember, this is the class with all the business logic.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">public\u00a0class\u00a0Task1Runnable\u00a0implements\u00a0TaskRunnable\u00a0{\r\n\r\n\u00a0\u00a0private\u00a0static\u00a0final\u00a0Logger\u00a0logger\u00a0=\u00a0Logger.getLogger(Task1Runnable.class);\r\n\r\n\u00a0\u00a0private\u00a0GenericTaskEntity\u00a0task;\r\n\r\n\u00a0\u00a0public\u00a0Task1Runnable()\u00a0{}\r\n\r\n\u00a0\u00a0public\u00a0Task1Runnable(GenericTaskEntity\u00a0task)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0this.task\u00a0=\u00a0task;\r\n\u00a0\u00a0}\r\n\r\n\u00a0\u00a0public\u00a0GenericTaskEntity\u00a0getTask()\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0return\u00a0task;\r\n\u00a0\u00a0}\r\n\r\n\u00a0\u00a0public\u00a0void\u00a0setTask(GenericTaskEntity\u00a0task)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0this.task\u00a0=\u00a0task;\r\n\u00a0\u00a0}\r\n\r\n\u00a0\u00a0@Override\r\n\u00a0\u00a0public\u00a0void\u00a0execute()\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0try\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0logger.info(\"Executing\u00a0task\u00a0\"\u00a0+\u00a0task.toString());\r\n\u00a0\u00a0\u00a0\u00a0}\u00a0catch\u00a0(InterruptedException\u00a0e)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0TODO\u00a0Auto-generated\u00a0catch\u00a0block\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0e.printStackTrace();\r\n\u00a0\u00a0\u00a0\u00a0}\u00a0finally\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0logger.info(\"Done\u00a0executing\u00a0task\u00a0\"\u00a0+\u00a0task.toString());\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0}\r\n}<\/pre>\n<p class=\"text-justify\" style=\"text-align: justify;\">That&#8217;s it. Now just add the task queue in the <code>task-queue-beans.xml<\/code>\u00a0and the <em>Runnable<\/em> class to the respective <code>task-runnable-beans.xml<\/code>\u00a0file so that <em>TaskQueueService<\/em> can start its respective <em>AcquireTaskThread<\/em>.<\/p>\n<\/section>\n<h1>Other Contributions<\/h1>\n<p style=\"text-align: justify;\">As an open source enthusiastic, I like to share my projects. Hoping that they will be useful to anybody, just as other projects have been to me. The projects can be downloaded from my <a href=\"https:\/\/github.com\/canchito-dev\">GitHub<\/a> repository. Below is a short list of some of my contributions.<\/p>\n<ul class=\"fa-ul list-docs\">\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a class=\"list-group-item\" href=\"http:\/\/canchito-dev.com\/projects\/bpt\">Bootstrap Password Toggler<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a class=\"list-group-item\" href=\"http:\/\/www.canchito-dev.com\/public\/blog\/2017\/04\/22\/build-a-rest-api-with-spring\/\">Build a REST API with Spring<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a class=\"list-group-item\" href=\"http:\/\/canchito-dev.com\/projects\/cwm\">Canchito Workflow Manager<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a class=\"list-group-item\" href=\"http:\/\/www.canchito-dev.com\/public\/blog\/2017\/04\/30\/integrate-activiti-bpm-with-spring\/\">Integrate Activiti with Spring<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a class=\"list-group-item\" href=\"http:\/\/canchito-dev.com\/projects\/mfm\">MINI-FRAMEWORK-MVC<\/a><\/li>\n<li><i class=\"fa-li fa fa-check-square\"><\/i><a href=\"https:\/\/github.com\/canchito-dev\">More&#8230;<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Flowable BPM turned into a workflow manager with features such as file transfer via FTP and Samba, integration with Amazon Web Service, file transcodification and analysis using FFmpeg and MediaInfo, and more..<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[31,46,30,47,45],"tags":[18,49,34,10,48],"class_list":["post-322","post","type-post","status-publish","format-standard","hentry","category-bpm","category-contribution","category-flowable","category-open-source","category-project","tag-bpm","tag-contribution","tag-flowable","tag-open-source","tag-project"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p8EwXo-5c","jetpack-related-posts":[{"id":184,"url":"http:\/\/www.canchito-dev.com\/public\/blog\/2018\/03\/30\/asynchronous-service-invocation-using-flowable\/","url_meta":{"origin":322,"position":0},"title":"Asynchronous Service Invocation using Flowable","author":"canchitodev","date":"March 30, 2018","format":false,"excerpt":"In this article, I will explain one possible method to solved some \"limitations\" encountered during the integration and implementation of\u00a0Flowable BPM, when executing long-running tasks, by implementing the Signallable Flowable Behavior and a database table as a task queue. Similar behavior can be achieved using Flowable's send task and receive\u2026","rel":"","context":"In &quot;BPM&quot;","block_context":{"text":"BPM","link":"http:\/\/www.canchito-dev.com\/public\/blog\/category\/bpm\/"},"img":{"alt_text":"CANCHITO-DEV: Task Queue Service","src":"https:\/\/i0.wp.com\/canchito-dev.com\/img\/cwm\/userguide\/canchito_dev_task_queue_service.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":356,"url":"http:\/\/www.canchito-dev.com\/public\/blog\/2019\/07\/05\/run-flowable-bpm-using-docker-and-mysql\/","url_meta":{"origin":322,"position":1},"title":"Run Flowable BPM using Docker and MySQL","author":"canchitodev","date":"July 5, 2019","format":false,"excerpt":"In this article, you will learn how to compile Flowable source code using MySQL as database source, and generate valid Docker images. Once you have the images, we will use Docker Compose for defining and running a multi-container Docker applications.","rel":"","context":"In &quot;BPM&quot;","block_context":{"text":"BPM","link":"http:\/\/www.canchito-dev.com\/public\/blog\/category\/bpm\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":372,"url":"http:\/\/www.canchito-dev.com\/public\/blog\/2020\/06\/07\/create-custom-service-tasks-for-flowable\/","url_meta":{"origin":322,"position":2},"title":"Create Custom Service Tasks for Flowable","author":"canchitodev","date":"June 7, 2020","format":false,"excerpt":"In\u00a0this\u00a0tutorial,\u00a0we\u00a0will\u00a0be\u00a0implementing\u00a0a\u00a0custom\u00a0service\u00a0task\u00a0in\u00a0Flowable\u00a0","rel":"","context":"In &quot;BPM&quot;","block_context":{"text":"BPM","link":"http:\/\/www.canchito-dev.com\/public\/blog\/category\/bpm\/"},"img":{"alt_text":"CANCHITO-DEV: Spring Initializr","src":"https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/initializr.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/initializr.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/initializr.png?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/initializr.png?resize=700%2C400 2x, https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/initializr.png?resize=1050%2C600 3x, https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/initializr.png?resize=1400%2C800 4x"},"classes":[]},{"id":471,"url":"http:\/\/www.canchito-dev.com\/public\/blog\/2020\/06\/27\/flowable-custom-engine-configuration\/","url_meta":{"origin":322,"position":3},"title":"Customizing Flowable Engine","author":"canchitodev","date":"June 27, 2020","format":false,"excerpt":"In this article, we will go into detail on how to customize Flowable's engine. Three changes to the engine will be done: (1) Change the database connection by modifying the data source and adding custom data source properties. (2)Use a strong UUID generator. (3)Implement a custom event handler.","rel":"","context":"In &quot;BPM&quot;","block_context":{"text":"BPM","link":"http:\/\/www.canchito-dev.com\/public\/blog\/category\/bpm\/"},"img":{"alt_text":"CANCHITO-DEV: Spring Initializr","src":"https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/initializr-1024x674.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/initializr-1024x674.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/initializr-1024x674.png?resize=525%2C300 1.5x"},"classes":[]},{"id":423,"url":"http:\/\/www.canchito-dev.com\/public\/blog\/2020\/05\/13\/deploying-flowable-in-a-docker-container-and-mysql-part-1\/","url_meta":{"origin":322,"position":4},"title":"Deploying Flowable in a Docker Container and MySQL (Part 1)","author":"canchitodev","date":"May 13, 2020","format":false,"excerpt":"In this post, you will learn how to adapt Flowable's war files to use MySQL as a database source. Once this is done, we will deploy them in a dockerized environment.","rel":"","context":"In &quot;BPM&quot;","block_context":{"text":"BPM","link":"http:\/\/www.canchito-dev.com\/public\/blog\/category\/bpm\/"},"img":{"alt_text":"CANCHITO-DEV: Tomcat Manager App","src":"https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/tomcat_manager_app.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/tomcat_manager_app.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/tomcat_manager_app.png?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/tomcat_manager_app.png?resize=700%2C400 2x, https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/tomcat_manager_app.png?resize=1050%2C600 3x, https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/tomcat_manager_app.png?resize=1400%2C800 4x"},"classes":[]},{"id":458,"url":"http:\/\/www.canchito-dev.com\/public\/blog\/2020\/05\/14\/deploying-flowable-in-a-docker-container-and-mysql-part-2\/","url_meta":{"origin":322,"position":5},"title":"Deploying Flowable in a Docker Container and MySQL (Part 2)","author":"canchitodev","date":"May 14, 2020","format":false,"excerpt":"This is the second part of our \"Deploying Flowable in a Docker Container and MySQL\" series. In this post, you will learn how to deploy Flowable's war files in a container running Tomcat, and connecting to another container running use MySQL database.","rel":"","context":"In &quot;BPM&quot;","block_context":{"text":"BPM","link":"http:\/\/www.canchito-dev.com\/public\/blog\/category\/bpm\/"},"img":{"alt_text":"CANCHITO-DEV: Tomcat Main","src":"https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/tomcat_main_page-1.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/tomcat_main_page-1.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/tomcat_main_page-1.png?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.canchito-dev.com\/public\/blog\/wp-content\/uploads\/2020\/05\/tomcat_main_page-1.png?resize=700%2C400 2x"},"classes":[]}],"jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/www.canchito-dev.com\/public\/blog\/wp-json\/wp\/v2\/posts\/322","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.canchito-dev.com\/public\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.canchito-dev.com\/public\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.canchito-dev.com\/public\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.canchito-dev.com\/public\/blog\/wp-json\/wp\/v2\/comments?post=322"}],"version-history":[{"count":11,"href":"http:\/\/www.canchito-dev.com\/public\/blog\/wp-json\/wp\/v2\/posts\/322\/revisions"}],"predecessor-version":[{"id":546,"href":"http:\/\/www.canchito-dev.com\/public\/blog\/wp-json\/wp\/v2\/posts\/322\/revisions\/546"}],"wp:attachment":[{"href":"http:\/\/www.canchito-dev.com\/public\/blog\/wp-json\/wp\/v2\/media?parent=322"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.canchito-dev.com\/public\/blog\/wp-json\/wp\/v2\/categories?post=322"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.canchito-dev.com\/public\/blog\/wp-json\/wp\/v2\/tags?post=322"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}