<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bonitasoft</title>
    <description>The latest articles on DEV Community by Bonitasoft (@bonitasoft).</description>
    <link>https://dev.to/bonitasoft</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1099%2Ff224b875-6333-4f28-84f0-56b28c332a58.jpg</url>
      <title>DEV Community: Bonitasoft</title>
      <link>https://dev.to/bonitasoft</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bonitasoft"/>
    <language>en</language>
    <item>
      <title>Bonita online documentation needs some Hacktoberfest 2022 love!</title>
      <dc:creator>Thomas Bouffard</dc:creator>
      <pubDate>Wed, 05 Oct 2022 08:01:14 +0000</pubDate>
      <link>https://dev.to/bonitasoft/bonita-online-documentation-needs-some-hacktoberfest-2022-love-3mab</link>
      <guid>https://dev.to/bonitasoft/bonita-online-documentation-needs-some-hacktoberfest-2022-love-3mab</guid>
      <description>&lt;h2&gt;
  
  
  What?
&lt;/h2&gt;

&lt;p&gt;Bonitasoft is taking part in &lt;strong&gt;&lt;a href="https://hacktoberfest.com/"&gt;Hacktoberfest&lt;/a&gt;,&lt;/strong&gt; a month-long celebration of open source software, where developers are encouraged to - and rewarded for - contributing to open source projects like Bonita.&lt;/p&gt;

&lt;p&gt;In this friendly, worldwide event, maintainers are invited to guide would-be contributors towards issues that will help move their projects forward, and contributors get the opportunity to give back - to projects they like, and to others they've just discovered.&lt;/p&gt;

&lt;p&gt;This year, we propose work on the design of the &lt;a href="https://documentation.bonitasoft.com/"&gt;online Bonita documentation web site&lt;/a&gt; 🔥.&lt;/p&gt;

&lt;p&gt;For example, there is an opportunity to improve the light and dark themes 🎨, improve the look and feel for mobile, and much more 😍.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This project is open to everyone&lt;/strong&gt; and no contribution is too small — bug fixes and documentation updates are valid ways of participating ✨.&lt;/p&gt;

&lt;h2&gt;
  
  
  How?
&lt;/h2&gt;

&lt;p&gt;It's easy! Register on &lt;a href="https://hacktoberfest.com/"&gt;Hacktoberfest&lt;/a&gt; with your GitHub account, search for issues to contribute, and send at least 4 pull requests ... After the 4th validated PR, you win the Hacktoberfest 2022 👕 or a 🌲 is planted in your name (first 40,000 participants, so get in there early!). &lt;/p&gt;

&lt;p&gt;To contribute to the design (a.k.a &lt;em&gt;bonita-documentation-theme&lt;/em&gt;) of the Bonita documentation site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check the &lt;a href="https://github.com/bonitasoft/bonita-documentation-theme/issues?q=is%3Aissue+is%3Aopen+label%3Ahacktoberfest+"&gt;opened issues&lt;/a&gt; available for Hacktoberfest.&lt;/li&gt;
&lt;li&gt;Find one that you are interested in and which is not already assigned to someone.&lt;/li&gt;
&lt;li&gt;Post a comment to mention you are willing to work on this topic. We will acknowledge and will assign it to you to inform the world!&lt;/li&gt;
&lt;li&gt;Work on a Pull Request. Ask any question if you are blocked or you need more details to complete your task.&lt;/li&gt;
&lt;li&gt;Submit your Pull Request. We will review it quickly and will work with you to ensure it is merged and visible on the documentation site&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are looking forward to your contributions 👋!&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>contributorswanted</category>
      <category>design</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The story of Bonita Documentation! The need for a new documentation site</title>
      <dc:creator>Thomas Bouffard</dc:creator>
      <pubDate>Wed, 08 Dec 2021 11:27:00 +0000</pubDate>
      <link>https://dev.to/bonitasoft/the-story-of-bonita-documentation-the-need-for-a-new-documentation-site-3p17</link>
      <guid>https://dev.to/bonitasoft/the-story-of-bonita-documentation-the-need-for-a-new-documentation-site-3p17</guid>
      <description>&lt;p&gt;Have you ever had a question, an issue, a need to know something about Bonita? If yes, you’ve probably visited the friendly Bonita Documentation!&lt;/p&gt;

&lt;p&gt;In March 2021, we launched the &lt;em&gt;new&lt;/em&gt; Bonita Documentation site, which offers fixes and improvements. If you want more details about the new site content, here’s the &lt;a href="https://community.bonitasoft.com/blog/brand-new-bonita-documentation-site"&gt;site go live announcement&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We want to share with you the story of the Bonita documentation evolution in a series to explain how and why the &lt;a href="https://www.bonitasoft.com/"&gt;Bonitasoft&lt;/a&gt; team decided to make this latest change.&lt;/p&gt;

&lt;p&gt;In our previous article, we described the fascinating history of &lt;a href="https://dev.to/bonitasoft/the-story-of-bonita-documentation-from-drupal-to-github-218g"&gt;the Bonita Documentation site 2016 version&lt;/a&gt;.&lt;br&gt;
Here we’ll show some of the issues we have faced over time and the solution we have been looking for to resolve them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issues with Bonita Documentation 2016
&lt;/h2&gt;

&lt;p&gt;The Bonita Documentation 2016 version was designed to manage documentation for Bonita Studio and Bonita Runtime only. By 2020, it was unable to support new needs, and we faced major issues in the user experience, maintenance, and operations that couldn’t be solved easily.&lt;/p&gt;

&lt;h3&gt;
  
  
  User eXperience
&lt;/h3&gt;

&lt;p&gt;Improvements made with the 2016 version of the Bonita documentation mainly focused on the content and how to update it, but  not so much on the User eXperience (UX).&lt;/p&gt;

&lt;p&gt;The site didn’t have a useful bookmark system. There weren’t real anchors in its pages, so it was hard to bookmark a specific section and to navigate between related content on pages and sections.&lt;/p&gt;

&lt;p&gt;The embedded search feature was also limited due to the lack of proper anchors. Clicking on a search result didn't send the user to the paragraph that matched the search request, but to the top of the page instead. There was then no other choice but to scroll in the page looking for the expected paragraph.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--evxedR1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5gphid5gzqme57l7j6gj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--evxedR1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5gphid5gzqme57l7j6gj.png" alt="Recycling papers" width="560" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Recycling” by &lt;a href="https://www.freeimages.com/photo/recycling-1239302"&gt;Griszka Niewiadomski&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;SEO was also an issue. Some pages of very old documentation versions were better indexed than their related page in the latest version, so search engines sometimes led the reader to outdated content. Navigation to new content required extra clicks and extra searches in the documentation site.&lt;/p&gt;

&lt;p&gt;One of the impacts of these issues was that readers could too easily miss the information they were searching for. This was not the best user experience and we wanted to do better.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maintenance
&lt;/h3&gt;

&lt;p&gt;The Bonita Documentation 2016 version involved custom &lt;a href="https://www.python.org/"&gt;Python&lt;/a&gt; scripts to aggregate document contents coming from various sources, using one repository per documentation component and a branch per version.&lt;/p&gt;

&lt;p&gt;This documentation content structure worked perfectly well, as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  branches were useful for for updates backport/cherry-pick/merge&lt;/li&gt;
&lt;li&gt;  repositories were useful for content segregation, access management, product and documentation lifecycle alignments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each branch in each repository was responsible for generating its documentation part; the aggregation scripts were in charge of assembling everything and adding the final styles.&lt;/p&gt;

&lt;p&gt;Initially this worked well, as there was only a single documentation component (the Bonita platform) and only a few versions.&lt;/p&gt;

&lt;p&gt;Over time though, the Bonita portfolio has grown and now contains more products (including Bonita Continuous Delivery, and Bonita Cloud), so more components and more versions were added to the documentation.&lt;/p&gt;

&lt;p&gt;Duplications of repositories began to appear and we had to make changes in multiple places. Inevitably more and more problems arose. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  At one time, it was possible to generate a PDF file for a given version of a component. This function was abandoned as it did not work properly, but was still present in all branches.&lt;/li&gt;
&lt;li&gt;  The build process of all versions was full of unused tools and dependencies. This slowed down the build.&lt;/li&gt;
&lt;li&gt;  We accepted changes in Markdown with custom syntax (for instance, to manage information and warning blocks), native HTML tags, and &lt;a href="https://fontawesome.com/"&gt;Font Awesome icons&lt;/a&gt;. But minor changes then had to be replicated to all repositories.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As noted, the Bonita Documentation 2016 was complex and hard to maintain. It used an aged technical stack and it was especially hard to build. Developers who may have been able to implement changes were not very encouraged to do so!&lt;/p&gt;

&lt;p&gt;We saw very few technical updates, fewer and fewer bug fixes, and the user experience issues remained.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operations
&lt;/h3&gt;

&lt;p&gt;The Bonita Documentation 2016 version had continuous deployment and preview environments. This was perfect for day-to-day work; changing the documentation content was straightforward. The changes were propagated from staging to production transparently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nONpX-0---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2ykhtce1d257a3wltgg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nONpX-0---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2ykhtce1d257a3wltgg.png" alt="Deploy previews with Jenkins when Pull Requests are created or update" width="880" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Pull Request Flow” taken from the &lt;a href="https://laurentleseigneur.github.io/agile-grenoble-2017/#/5/8"&gt;Agile Grenoble 2017 presentation “Fluidifier la production de la documentation”&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But we also faced operational pains.&lt;/p&gt;

&lt;p&gt;Adding a new component version (for instance, when preparing a new Bonita beta version) involved multiple actors and synchronization.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The configuration to actually manage the version was spread across several locations.&lt;/li&gt;
&lt;li&gt;  Synchronization was done using tickets, and direct conversations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lack of ability to self-service updates slowed down the process a lot and generated frustration.&lt;/p&gt;

&lt;p&gt;The documentation site build, and deployment to the preview and production environments, were all managed with internally-operated &lt;a href="https://en.wikipedia.org/wiki/Continuous_integration"&gt;Continuous Integration&lt;/a&gt; servers (&lt;a href="https://www.jenkins.io/"&gt;Jenkins&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Internally-operated meant dealing with Jenkins and server updates. As it involved a large amount of custom scripts and Jenkins jobs, this also meant maintenance to follow the Jenkins evolutions.&lt;/p&gt;

&lt;p&gt;The pre-production and production environments were composed of front-end and search (&lt;a href="https://solr.apache.org/"&gt;Solr&lt;/a&gt;) servers, also operated internally. This was another area for regular maintenance costs.&lt;/p&gt;

&lt;p&gt;As we didn’t rely on a &lt;a href="https://en.wikipedia.org/wiki/Content_delivery_network"&gt;CDN&lt;/a&gt;, the latency could be high depending on the location a user was browsing the documentation from.&lt;/p&gt;

&lt;h3&gt;
  
  
  The previous Drupal-based documentation
&lt;/h3&gt;

&lt;p&gt;Prior to the Bonita Documentation 2016 version, Bonita documentation (for Bonita BPM v6.0 to v7.2) was managed on Drupal.&lt;/p&gt;

&lt;p&gt;This content had to stay online for a transition period, up until the versions reached end-of-life. As often happens with legacy assets, it was still available years later.&lt;/p&gt;

&lt;p&gt;There were no plans for decommissioning or migrating, and it contained very old content which hadn’t been updated for a while.&lt;/p&gt;

&lt;p&gt;It had its own dedicated infrastructure still live more than 4 years after the rollout of &lt;a href="https://dev.to/bonitasoft/the-story-of-bonita-documentation-from-drupal-to-github-218g"&gt;the Bonita Documentation site 2016  version&lt;/a&gt;. The operations team had to deal with security (stack hard to update) and user experience concerns (no changes to the site while browsers have evolved, resulting in some broken features).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aqb6NTvZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0r2py1vxlahwxd1otel7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aqb6NTvZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0r2py1vxlahwxd1otel7.png" alt="Drawing: Dream written on a wall by a little girl" width="698" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/photos/rlRRIvWNJJo"&gt;Thiébaud Faix&lt;/a&gt; on &lt;a href="https://unsplash.com/"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The New Solution: What We Dreamt About
&lt;/h2&gt;

&lt;p&gt;All the issues explained above began to have more and more impact on Bonita documentation users. We really wanted to get in there and improve the site!&lt;/p&gt;

&lt;p&gt;We first prototyped a new solution based on Jekyll for HTML generation, keeping most of the existing Markdown content and the Python aggregator. We also investigated moving the search solution from Solr to &lt;a href="https://www.elastic.co/elasticsearch/"&gt;ElasticSearch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While having a true static site was a great improvement, a lot of issues remained unresolved.&lt;/p&gt;

&lt;p&gt;The prototype only addressed a part of the user experience issues; maintenance and the operations sides still presented issues. The site still included a lot of custom code in particular for the content aggregation.&lt;/p&gt;

&lt;p&gt;So this approach was not a game changer, although it was a way to do basically the same thing better. But ultimately it didn’t provide enough improvements.&lt;/p&gt;

&lt;p&gt;So we decided to change our direction, go back to simplicity, and approach everything globally.&lt;/p&gt;

&lt;h3&gt;
  
  
  User experience (UX)
&lt;/h3&gt;

&lt;p&gt;The first prototype confirmed that we needed a static site that could provide a good UX especially on mobile (which wasn’t that good in the existing site) and good SEO out of the box.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maintenance
&lt;/h3&gt;

&lt;p&gt;Reducing maintenance time and complexity was one of our main concerns.&lt;/p&gt;

&lt;p&gt;We needed a simpler solution to maintain and deploy; we wanted to rely on existing and widely used tools (a lot of products have the same documentation needs as ours, so solutions exist for our use case), and reduce customization at the minimum (theming).&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dev.to/bonitasoft/the-story-of-bonita-documentation-from-drupal-to-github-218g"&gt;Bonita Documentation site 2016 version&lt;/a&gt; worked perfectly for porting documentation content changes from version to version. We wanted to keep that, but have a simpler build that wouldn’t be split across repositories.&lt;/p&gt;

&lt;p&gt;For a long time, keeping Markdown as a markup language was mandatory. We wanted to avoid doing content migration and training documentation contributors, but this should not stop us from using a better adapted solution if it supports only other languages (as long as we can migrate the existing content and it is easy to learn). We wanted to have a markup language for text diff/merge with Git and Markdown was one way to achieve that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operations
&lt;/h3&gt;

&lt;p&gt;We needed to get rid of silos, to have a more self-serve solution to avoid tickets, team synchronization issues, and bottlenecks.&lt;/p&gt;

&lt;p&gt;This also meant using configuration as code as much as possible, and automation for continuous preview and deployment. So we imagined a more comprehensive solution where we would no longer operate the Continuous Integration/Deployment, search, and front-end servers ourselves.&lt;/p&gt;

&lt;p&gt;We wanted to focus on using them, not on maintaining and upgrading them. So we felt that this would probably involve using a &lt;a href="https://en.wikipedia.org/wiki/Platform_as_a_service"&gt;PAAS&lt;/a&gt; solution, to provide more features for &lt;a href="https://en.wikipedia.org/wiki/High_availability"&gt;High Availability&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Content_delivery_network"&gt;Content Delivery Network&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the old Drupal solution, we decided we needed to find a way to keep the content but drop the related infrastructure, or be ready to definitively remove it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZH56aTWw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/85ucdhydj081oguqlrpq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZH56aTWw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/85ucdhydj081oguqlrpq.jpg" alt="A crystal ball" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/photos/xU5Mqq0Chck"&gt;Drew Beamer&lt;/a&gt; on &lt;a href="https://unsplash.com/"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Coming soon
&lt;/h2&gt;

&lt;p&gt;This article presents the issues of &lt;a href="https://dev.to/bonitasoft/the-story-of-bonita-documentation-from-drupal-to-github-218g"&gt;the Bonita Documentation site 2016 version&lt;/a&gt; and why we needed to provide a refreshed site. In  it, I have outlined both the issues and our “need to have” and “want to have” requirements to select a new solution for improvements.&lt;/p&gt;

&lt;p&gt;In the next article, we’ll explain the actual technical choices we made for the new online documentation, and what we learned about our new technical stack from the migration. (Hint: we’re still here, and so is the &lt;a href="https://documentation.bonitasoft.com/bonita/latest/"&gt;Bonita documentation&lt;/a&gt;!)&lt;/p&gt;

</description>
      <category>documentation</category>
      <category>bonita</category>
      <category>github</category>
      <category>markdown</category>
    </item>
    <item>
      <title>The story of Bonita Documentation! From Drupal to GitHub</title>
      <dc:creator>Thomas Bouffard</dc:creator>
      <pubDate>Tue, 30 Nov 2021 15:38:45 +0000</pubDate>
      <link>https://dev.to/bonitasoft/the-story-of-bonita-documentation-from-drupal-to-github-218g</link>
      <guid>https://dev.to/bonitasoft/the-story-of-bonita-documentation-from-drupal-to-github-218g</guid>
      <description>&lt;p&gt;Have you ever had a question, an issue, a need to know something about Bonita? If yes, you’ve probably visited the friendly Bonita Documentation!&lt;/p&gt;

&lt;p&gt;Last March 2021, we launched the &lt;em&gt;new&lt;/em&gt; Bonita Documentation site, which provides a lot of fixes and improvements. If you want more details about the new site content, here’s the &lt;a href="https://community.bonitasoft.com/blog/brand-new-bonita-documentation-site"&gt;site go live announcement&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We want to share with you the story of the Bonita documentation evolution. We’ll start with this article, first in a series to explain how and why the &lt;a href="https://www.bonitasoft.com/"&gt;Bonitasoft&lt;/a&gt; team decided to make this latest change.&lt;/p&gt;

&lt;p&gt;Here we’ll describe the previous iteration of the Bonita documentation (may it rest in peace), the fascinating history of our documentation and some of the issues we faced over the time.&lt;/p&gt;

&lt;p&gt;In the following articles, we’ll explain the solution we were looking for, the technical choices we made, and what we learned from our new technical stack during the migration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonita documentation: Know the past, understand the present
&lt;/h2&gt;

&lt;p&gt;The Bonita online documentation was revamped in 2016. The previous &lt;a href="https://www.drupal.org/"&gt;Drupal&lt;/a&gt;-based site was deprecated and a new site, fully custom made, was introduced to host the documentation starting with &lt;a href="https://www.bonitasoft.com/"&gt;Bonita BPM v7.3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This first revision was motivated by the existence of a lot of issues in the existing solution, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Content could only be updated by the Bonitasoft internal technical writer (a single person), so if you saw a simple typo, for instance, you had no way to fix it yourself. You had to reach the person responsible, or create a ticket. This was a bottleneck and led to a lack of ownership in particular by the Bonitasoft Product and R&amp;amp;D teams who never felt motivated to improve documentation because the process was too heavy.&lt;/li&gt;
&lt;li&gt;  Versioning was hard to manage, in particular reporting updates from version to version was difficult (and not possible to do
automatically), which meant is was often forgotten and not in sync with the Bonita version release.&lt;/li&gt;
&lt;li&gt;  There was no real preview of the final rendering prior to publishing to production, which led to mistakes, rework and dissatisfaction.&lt;/li&gt;
&lt;li&gt;  Technical updates in the production environment were rare and painful. This Drupal site had been customized by the Bonitasoft IT Team, so Drupal updates needed custom code/configuration as well.&lt;/li&gt;
&lt;li&gt;  It was necessary for Bonita users to login to access the documentation, and we may have lost some potential Bonita users
because of that. We definitely had users that did not Read The Friendly Documentation!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The development of a new documentation solution started in January 2016 to be ready for the Bonita BPM v7.3 release.&lt;/p&gt;

&lt;h2&gt;
  
  
  New and improved!
&lt;/h2&gt;

&lt;p&gt;The internal Bonitasoft team decided that the documentation content should be public and hosted in a GitHub repository.&lt;/p&gt;

&lt;p&gt;We introduced with the GitHub documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  collaborative contribution flow with &lt;a href="https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests"&gt;Pull Requests&lt;/a&gt; only&lt;/li&gt;
&lt;li&gt;  content is written using &lt;a href="https://en.wikipedia.org/wiki/Markdown"&gt;Markdown&lt;/a&gt; syntax instead of filling a form using pseudo-wysiwyg text. This separation between the content and its presentation allowed more flexibility (initially we could generate documentation in both PDF and HTML)&lt;/li&gt;
&lt;li&gt;  updated content is continuously deployed to production&lt;/li&gt;
&lt;li&gt;  a new and better search engine is integrated within the site&lt;/li&gt;
&lt;li&gt;  no more login is needed to access to the documentation&lt;/li&gt;
&lt;li&gt;  preview environments are available and built in the same way as the production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FD-Y33gE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fl6ot54pa4zdguk5mwup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FD-Y33gE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fl6ot54pa4zdguk5mwup.png" alt="An egyptian pyramid" width="750" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/photos/I-mGeOT1HKg"&gt;Jeremy Bezanger&lt;/a&gt; on &lt;a href="https://unsplash.com/"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These improvements fixed the main issues of the previous Drupal solution.&lt;/p&gt;

&lt;p&gt;For Bonita users (community or customers), Bonita Documentation site v2016 meant that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The documentation content was updated frequently, with a version-to-version report with a Git merge. Small changes could be done by anyone and pushed to production quickly by merging pull requests (and just a few minutes’ wait for the production site to be updated).&lt;/li&gt;
&lt;li&gt;  The documentation was released at the same time as the Bonita beta and GA versions.&lt;/li&gt;
&lt;li&gt;  Bonita users can contribute directly to the content instead of requesting changes (in particular for very small changes like typos).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Bonita developers, Bonitasoft Product and Support Teams:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  They can easily produce and update Bonita documentation.&lt;/li&gt;
&lt;li&gt;  Documentation issues and feedback can be quickly integrated.&lt;/li&gt;
&lt;li&gt;  Contributions are reviewed and discussed by technical pairs to be sure content is accurate.&lt;/li&gt;
&lt;li&gt;  Updates are tracked in the Git history for easier content maintenance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The go live for Bonita documentation on GitHub was announced with a blog post on &lt;a href="https://community.bonitasoft.com/blog/collaborate-bonita-bpm-documentation"&gt;September 14, 2016&lt;/a&gt;, and this solution was used until March 2021.*&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZH56aTWw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/85ucdhydj081oguqlrpq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZH56aTWw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/85ucdhydj081oguqlrpq.jpg" alt="A crystal ball" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/photos/xU5Mqq0Chck"&gt;Drew Beamer&lt;/a&gt; on &lt;a href="https://unsplash.com/"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Coming soon
&lt;/h2&gt;

&lt;p&gt;Then...everything changed once again. In my &lt;a href="https://dev.to/bonitasoft/the-story-of-bonita-documentation-the-need-for-a-new-documentation-site-3p17"&gt;next blog post&lt;/a&gt;, I’ll tell you why.&lt;/p&gt;

&lt;p&gt;Thank you to &lt;a href="https://twitter.com/LLeseigneur"&gt;Laurent Leseigneur&lt;/a&gt; and &lt;a href="https://github.com/educhastenier"&gt;Emmanuel Duchastenier&lt;/a&gt; for their review of this article.&lt;/p&gt;

&lt;p&gt;*If you want to know more about this first migration, an overall presentation in French is available in a set of &lt;a href="https://laurentleseigneur.github.io/agile-grenoble-2017/#/5"&gt;public slides&lt;/a&gt; (use the down arrow to pass to the next slide). It gives more details about this story, and the technical solution.&lt;/p&gt;

</description>
      <category>documentation</category>
      <category>bonita</category>
      <category>markdown</category>
      <category>drupal</category>
    </item>
    <item>
      <title>Embed Bonita Engine in a Spring Boot application</title>
      <dc:creator>Emmanuel Duchastenier</dc:creator>
      <pubDate>Fri, 12 Jul 2019 12:50:09 +0000</pubDate>
      <link>https://dev.to/bonitasoft/embed-bonita-engine-in-a-spring-boot-application-4377</link>
      <guid>https://dev.to/bonitasoft/embed-bonita-engine-in-a-spring-boot-application-4377</guid>
      <description>&lt;p&gt;This tutorial is an example of how to embed the Bonita Engine (BPM workflow engine) in a &lt;strong&gt;Spring Boot&lt;/strong&gt; application.&lt;br&gt;&lt;br&gt;
The proposed use-case is an application based on a process that allows someone to request a loan from their bank. This request will be reviewed, approved or rejected by the bank which will give explanations for this decision.&lt;/p&gt;
&lt;h2&gt;
  
  
  Scope
&lt;/h2&gt;

&lt;p&gt;In this tutorial, you will learn how to write an application, using the Spring Boot framework, that integrates the Bonita Execution Engine to run processes.&lt;br&gt;
You will learn how to configure the Bonita Engine to point to the database of your choice and tune the connection pool.&lt;br&gt;
You will learn how to build processes programmatically, deploy and execute them.&lt;br&gt;
You will also learn how to deploy processes generated with &lt;a href="https://documentation.bonitasoft.com/bonita/current/bonita-bpm-overview" rel="noopener noreferrer"&gt;Bonita Studio&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  TLDR;
&lt;/h3&gt;

&lt;p&gt;The full source code of this tutorial can be accessed directly, in 2 different flavours:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://github.com/bonitasoft/bonita-examples/tree/master/bonita-loan-request-application/loan-request-app-gradle-kotlin" rel="noopener noreferrer"&gt;first example&lt;/a&gt; illustrates how to build the application with &lt;a href="https://gradle.org/" rel="noopener noreferrer"&gt;Gradle&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://github.com/bonitasoft/bonita-examples/tree/master/bonita-loan-request-application/loan-request-app-maven-kotlin" rel="noopener noreferrer"&gt;second example&lt;/a&gt; illustrates how to build the application with &lt;a href="https://maven.apache.org/" rel="noopener noreferrer"&gt;Maven&lt;/a&gt;.
The &lt;a href="https://github.com/bonitasoft/bonita-examples/tree/master/bonita-loan-request-application/loan-request-app-gradle-kotlin" rel="noopener noreferrer"&gt;full tutorial details&lt;/a&gt; are provided in the Gradle example, but everything works
the same in the Maven example. Only the build part is specific.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Database
&lt;/h3&gt;

&lt;p&gt;If you just want to run an embedded H2 database, nothing is required.&lt;/p&gt;

&lt;p&gt;To have your application point to a MySQL, PostgreSQL, Microsoft SQL Server, or Oracle database make sure you have a Database server up and running, and that it contains a schema dedicated to the Bonita Engine (default name is &lt;code&gt;bonita&lt;/code&gt;).&lt;br&gt;&lt;br&gt;
For deeper details on database preparation for Bonita, see &lt;a href="https://documentation.bonitasoft.com/bonita/current/database-configuration" rel="noopener noreferrer"&gt;the specific documentation page&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Then read below how to configure the database access.&lt;/p&gt;
&lt;h3&gt;
  
  
  Processes
&lt;/h3&gt;

&lt;p&gt;This tutorial assumes you have basic knowledge of BPMN / process design.&lt;/p&gt;
&lt;h2&gt;
  
  
  Use case
&lt;/h2&gt;

&lt;p&gt;For this example, we will develop and interact with the following process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjixct237pxziilvnadvt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjixct237pxziilvnadvt.png" alt="Loan Request process diagram"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's write the application step by step
&lt;/h2&gt;

&lt;p&gt;In this example, we propose to use &lt;strong&gt;Gradle&lt;/strong&gt; as the build tool, and &lt;strong&gt;Kotlin&lt;/strong&gt; as the programming language.&lt;br&gt;
If you are not familiar with Gradle, there is a &lt;a href="https://github.com/bonitasoft/bonita-examples/tree/master/bonita-loan-request-application/loan-request-app-maven-kotlin" rel="noopener noreferrer"&gt;Maven version of this example&lt;/a&gt;.&lt;br&gt;
If you are not familiar with Kotlin, don't worry, it can be read easily if you know Java or a similar language.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bootstrap of the application, using Spring Boot
&lt;/h3&gt;

&lt;p&gt;Let's write a Gradle build (file &lt;code&gt;build.gradle.kts&lt;/code&gt;) with the minimum Spring Boot + Kotlin requirements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jetbrains.kotlin.gradle.tasks.KotlinCompile&lt;/span&gt;

&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.boot"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"2.1.6.RELEASE"&lt;/span&gt;
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"io.spring.dependency-management"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"1.0.7.RELEASE"&lt;/span&gt;
    &lt;span class="nf"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jvm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"1.3.41"&lt;/span&gt;
    &lt;span class="nf"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"plugin.spring"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"1.3.41"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;repositories&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;mavenCentral&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;jcenter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Embed an application server:&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.boot:spring-boot-starter"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Libs to code in Kotlin:&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.jetbrains.kotlin:kotlin-reflect"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.jetbrains.kotlin:kotlin-stdlib-jdk8"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sourceCompatibility&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;JavaVersion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;VERSION_1_8&lt;/span&gt;

&lt;span class="c1"&gt;// configure Kotlin compiler:&lt;/span&gt;
&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;KotlinCompile&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;kotlinOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;freeCompilerArgs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-Xjsr305=strict"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;jvmTarget&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.8"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write the main Spring Boot class to launch our application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.bonitasoft.loanrequest&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.boot.autoconfigure.SpringBootApplication&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.boot.runApplication&lt;/span&gt;

&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoanRequestApplication&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;runApplication&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LoanRequestApplication&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the current state, our application can already be run (but does not do anything) by typing in the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./gradlew bootRun
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and can then be accessed at &lt;a href="http://localhost:8080/" rel="noopener noreferrer"&gt;http://localhost:8080/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding the Bonita Engine
&lt;/h3&gt;

&lt;p&gt;As a next step, let's add the Bonita Engine in the equation in our &lt;code&gt;build.gradle.kts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bonitaEngineVersion&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"7.9.0"&lt;/span&gt;

    &lt;span class="c1"&gt;// adding dependency on bonita-engine-spring-boot-starter automatically provides&lt;/span&gt;
    &lt;span class="c1"&gt;// and starts a Bonita Engine when used in a Spring Boot application:&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.bonitasoft.engine:bonita-engine-spring-boot-starter:$bonitaEngineVersion"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// use bonita-client to be able to interact with the running Engine&lt;/span&gt;
    &lt;span class="c1"&gt;// to deploy and run instances of processes:&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.bonitasoft.engine:bonita-client:$bonitaEngineVersion"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Add the database driver we want Bonita to use:&lt;/span&gt;
    &lt;span class="nf"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.h2database:h2:1.4.199"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The magic of Spring Boot happens, and a Bonita Engine is automatically started when our application starts.&lt;br&gt;
We can see Engine startup logs in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|09:44:15.601|main|INFO |o.b.p.s.ScriptExecutor| configuration for Database vendor: h2
|09:44:15.989|main|INFO |o.b.p.s.PlatformSetup| Connected to 'h2' database with url: 'jdbc:h2:file:./build/h2_database/bonita' with user: 'BONITA'
|09:44:16.341|main|INFO |o.b.p.s.ScriptExecutor| Executed SQL script file:/home/manu/.gradle/caches/modules-2/files-2.1/org.bonitasoft.platform/platform-resources/7.9.0/c183cb/platform-resources-7.9.0.jar!/sql/h2/createTables.sql
...
|09:44:26.437|main|INFO |o.b.e.a.i.PlatformAPIImpl| THREAD_ID=1 | HOSTNAME=manu-laptop | Start service of platform : org.bonitasoft.engine.classloader.ClassLoaderServiceImpl
|09:44:26.438|main|INFO |o.b.e.a.i.PlatformAPIImpl| THREAD_ID=1 | HOSTNAME=manu-laptop | Start service of platform : org.bonitasoft.engine.cache.ehcache.PlatformEhCacheCacheService
|09:44:26.490|main|INFO |o.b.e.a.i.PlatformAPIImpl| THREAD_ID=1 | HOSTNAME=manu-laptop | Start service of platform : org.bonitasoft.engine.service.BonitaTaskExecutor
...
|09:44:26.708|main|INFO |o.b.e.a.i.t.SetServiceState| THREAD_ID=1 | HOSTNAME=manu-laptop | TENANT_ID=1 | start tenant-level service org.bonitasoft.engine.cache.ehcache.EhCacheCacheService on tenant with ID 1
|09:44:26.718|main|INFO |o.b.e.a.i.t.SetServiceState| THREAD_ID=1 | HOSTNAME=manu-laptop | TENANT_ID=1 | start tenant-level service org.bonitasoft.engine.business.data.impl.JPABusinessDataRepositoryImpl on tenant with ID 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Let's code our first process
&lt;/h3&gt;

&lt;p&gt;Our platform is running, we can now create a LoanRequestProcessBuilder class that builds a Bonita process and returns a DesignProcessDefinition.&lt;br&gt;
Let's build the process designed on the diagram above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.bonitasoft.loanrequest.process&lt;/span&gt;

&lt;span class="c1"&gt;// imports removed for readability&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;ACTOR_REQUESTER&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Requester"&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;ACTOR_VALIDATOR&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Validator"&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;START_EVENT&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Start Request"&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;REVIEW_REQUEST_TASK&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Review Request"&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;DECISION_GATEWAY&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"isAccepted"&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;SIGN_CONTRACT_TASK&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Sign contract"&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;NOTIFY_REJECTION_TASK&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Notify rejection"&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;ACCEPTED_END_EVENT&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Accepted"&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;REJECTED_END_EVENT&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Rejected"&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;CONTRACT_AMOUNT&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"amount"&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoanRequestProcessBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;buildExampleProcess&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;DesignProcessDefinition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;processBuilder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ProcessDefinitionBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;createNewInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LoanRequest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;// Define the actors of the process:&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ACTOR_REQUESTER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// only requester can initiate a new process&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ACTOR_VALIDATOR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// only requester can initiate a new process&lt;/span&gt;
        &lt;span class="c1"&gt;// Define the tasks&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addUserTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;REVIEW_REQUEST_TASK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ACTOR_VALIDATOR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addUserTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SIGN_CONTRACT_TASK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ACTOR_REQUESTER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Imagine this task involve paper signing&lt;/span&gt;

        &lt;span class="c1"&gt;// For completion, this auto-task should have a connector on it,&lt;/span&gt;
        &lt;span class="c1"&gt;// to notify the rejection (through email connector, for example):&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addAutomaticTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NOTIFY_REJECTION_TASK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// Define the events:&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addStartEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;START_EVENT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEndEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ACCEPTED_END_EVENT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEndEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;REJECTED_END_EVENT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;// Define the Gateway:&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addGateway&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DECISION_GATEWAY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;GatewayType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;EXCLUSIVE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;// Define transitions:&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;START_EVENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;REVIEW_REQUEST_TASK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;REVIEW_REQUEST_TASK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;DECISION_GATEWAY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DECISION_GATEWAY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SIGN_CONTRACT_TASK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="c1"&gt;// let's simulate a human decision with a random accepted / rejected decision:&lt;/span&gt;
                &lt;span class="nc"&gt;ExpressionBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;createGroovyScriptExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"random decision"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"new java.util.Random(System.currentTimeMillis()).nextBoolean()"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"java.lang.Boolean"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addDefaultTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DECISION_GATEWAY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;NOTIFY_REJECTION_TASK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Default transition, taken is expression above returns false&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SIGN_CONTRACT_TASK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ACCEPTED_END_EVENT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NOTIFY_REJECTION_TASK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;REJECTED_END_EVENT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// Define a contract on the process initiation:&lt;/span&gt;
        &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addContract&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;addInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CONTRACT_AMOUNT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Amount of the loan requested"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;// Here we imagine a more complex contract with more inputs...&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;processBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then this process must be deployed and enabled. Let's create a dedicated class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.bonitasoft.loanrequest.process&lt;/span&gt;

&lt;span class="c1"&gt;// imports...&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProcessDeployer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Throws&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BonitaException&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;deployAndEnableProcessWithActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;designProcessDefinition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;DesignProcessDefinition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="n"&gt;requesterActor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="n"&gt;requesterUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="n"&gt;validatorActor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="n"&gt;validatorUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ProcessDefinition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Create the Actor Mapping with our Users:&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;requester&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requesterActor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;requester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requesterUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;validator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validatorActor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validatorUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;actorMapping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ActorMapping&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;actorMapping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requester&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;actorMapping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// Create the Business Archive to deploy:&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;businessArchive&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BusinessArchiveBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;createNewBusinessArchive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProcessDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;designProcessDefinition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="c1"&gt;// set the actor mapping so that the process is resolved and can then be enabled:&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setActorMapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actorMapping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processAPI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;processDefinition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;businessArchive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;enableProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processDefinition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;processDefinition&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's now call our build and deploy methods from our main application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;apiClient&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// Log in on Engine API:&lt;/span&gt;
&lt;span class="nf"&gt;loginAsTenantAdministrator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// Create business users to interact with the process:&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;requester&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createNewUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"requester"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bpm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Requester"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"LoanRequester"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;validator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createNewUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"validator"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bpm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Validator"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"LoanValidator"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Use this newly created users to create and execute the process flow:&lt;/span&gt;
&lt;span class="nf"&gt;loginWithAnotherUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requester&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;processDefinition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAndDeployProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requester&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Utility function to log in to Bonita with the provided Administrator User:&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;loginAsTenantAdministrator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TENANT_ADMIN_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;TENANT_ADMIN_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Utility function to create a User in Bonita:&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createNewUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;identityAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Utility function to log in to Bonita with a specific User:&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;loginWithAnotherUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bpm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createAndDeployProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initiator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ProcessDefinition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create the process:&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;designProcessDefinition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LoanRequestProcessBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;buildExampleProcess&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// Deploy the process and enable it:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ProcessDeployer&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;deployAndEnableProcessWithActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;designProcessDefinition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ACTOR_REQUESTER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;initiator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ACTOR_VALIDATOR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, our process is created and deployed in Bonita.&lt;br&gt;
Let's check this by writing a HTTP endpoint that lists all existing processes.&lt;br&gt;
To do so, we need to add a simple Spring Boot dependency and its JSON library, to return the results in JSON format:&lt;br&gt;
In this file &lt;code&gt;build.gradle.kts&lt;/code&gt;, in the &lt;code&gt;dependencies { }&lt;/code&gt; section&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// Libs to expose Rest API through an embedded application server:&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.boot:spring-boot-starter-web:2.1.6.RELEASE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can write a simple &lt;a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html" rel="noopener noreferrer"&gt;Spring MVC controller&lt;/a&gt; to expose our processes through an HTTP API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.bonitasoft.loanrequest.api&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.bonitasoft.engine.api.APIClient&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.bonitasoft.engine.bpm.process.ProcessDeploymentInfo&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.bonitasoft.engine.search.SearchOptionsBuilder&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.bonitasoft.loanrequest.process.CONTRACT_AMOUNT&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.GetMapping&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.PathVariable&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.RestController&lt;/span&gt;

&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="c1"&gt;// our apiClient is automagically :-) injected by Spring:&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProcessController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Expose the deployed processes through Rest APIs:&lt;/span&gt;
    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/processes"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProcessDeploymentInfo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"install"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"install"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;searchProcessDeploymentInfos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SearchOptionsBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;
        &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, let's restart our application with &lt;code&gt;./gradlew bootRun&lt;/code&gt;.&lt;br&gt;
Our application starts, creates and deploys our process.&lt;br&gt;
Let's access &lt;a href="http://localhost:8080/processes" rel="noopener noreferrer"&gt;http://localhost:8080/processes&lt;/a&gt; to list our processes. The result should be something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LoanRequest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"displayDescription"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"deploymentDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-07-05T09:33:21.490+0000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"deployedBy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"configurationState"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RESOLVED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"activationState"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ENABLED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"processId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7450221031288910000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"displayName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LoanRequest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"lastUpdateDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-07-05T09:33:21.607+0000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"iconPath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beware that the field "processId" is incorrect, due to a limitation of the JSON / Javascript &lt;code&gt;Long&lt;/code&gt; size, which is smaller that the &lt;code&gt;Long&lt;/code&gt; size in Java (or Kotlin). The symptom is that the last digits are 0000 instead of a real value.&lt;br&gt;
This limitation only exists if you use JSON / Javascript to display a &lt;code&gt;Long&lt;/code&gt; value.&lt;br&gt;
To bypass this limitation, we could convert this value as a String before returning it through Rest APIs.&lt;/p&gt;
&lt;h3&gt;
  
  
  Deploy a process designed with Bonita Studio
&lt;/h3&gt;

&lt;p&gt;If you have designed your process using Bonita Studio (graphical tool), you can deploy the generated &lt;code&gt;.bar&lt;/code&gt; file through the APIs as well. To do so, place your .bar file somewhere in the classpath of the application and load it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProcessLoader&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;loadProcessFromBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;barFilePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;BusinessArchive&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;javaClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getResourceAsStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;barFilePath&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;resourceAsStream&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BusinessArchiveFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readBusinessArchive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resourceAsStream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and make the call to the "load" function and then deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;processFromBar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ProcessLoader&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;loadProcessFromBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/SimpleProcess--1.0.bar"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;ProcessDeployer&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;deployAndEnableBusinessArchiveWithoutAnyActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processFromBar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that our process named &lt;code&gt;SimpleProcess&lt;/code&gt; is now deployed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;|15:50:59.107|main|INFO |o.b.e.b.BusinessArchiveServiceImpl| &lt;span class="nv"&gt;THREAD_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 | &lt;span class="nv"&gt;HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ubuntu | &lt;span class="nv"&gt;TENANT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 | The user &amp;lt;requester&amp;gt; has installed process &amp;lt;SimpleProcess&amp;gt; &lt;span class="k"&gt;in &lt;/span&gt;version &amp;lt;1.0&amp;gt; with &lt;span class="nb"&gt;id&lt;/span&gt; &amp;lt;6733385816066783268&amp;gt;
|15:50:59.119|BonitaTaskExecutor|INFO |o.b.e.c.ClassLoaderServiceImpl| &lt;span class="nv"&gt;THREAD_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;60 | &lt;span class="nv"&gt;HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ubuntu | Refreshing classloader with key: PROCESS:6733385816066783268
|15:50:59.200|main|INFO |o.b.e.a.i.t.p.EnableProcess| &lt;span class="nv"&gt;THREAD_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 | &lt;span class="nv"&gt;HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ubuntu | &lt;span class="nv"&gt;TENANT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 | The user &amp;lt;requester&amp;gt; has enabled process &amp;lt;SimpleProcess&amp;gt; &lt;span class="k"&gt;in &lt;/span&gt;version &amp;lt;1.0&amp;gt; with &lt;span class="nb"&gt;id&lt;/span&gt; &amp;lt;6733385816066783268&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full example can be found in the &lt;a href="https://github.com/bonitasoft/bonita-examples/blob/master/bonita-loan-request-application/loan-request-app-gradle-kotlin/src/main/kotlin/org/bonitasoft/loanrequest/LoanRequestApplication.kt" rel="noopener noreferrer"&gt;source code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: be aware that a .bar file generated by a specific Studio version is compatible only with the same version of Bonita you imported in your Gradle dependencies. If you update the dependency to a newer version, you may need to regenerate the .bar file with the same newer version of Bonita Studio.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interact with the process
&lt;/h3&gt;

&lt;p&gt;Our platform and process are now ready to be executed.&lt;br&gt;
We have to set interactions with the process to continue the execution flow.&lt;br&gt;
The interactions depend on the design of our process.&lt;br&gt;
Here is an example of the application flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;executeProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requester&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;processDefinition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@Throws&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BonitaException&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;executeProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initiator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;processDefinition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ProcessDefinition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Start a new Loan request with an amount of 12000.0 (€ Euro):&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;processInstance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startProcessWithInputs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processDefinition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;mapOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CONTRACT_AMOUNT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;12000.0&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

    &lt;span class="c1"&gt;// Now the validator needs to review it:&lt;/span&gt;
    &lt;span class="nf"&gt;loginWithAnotherUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Wait for the user task "Review Request" to be ready to execute, using a user member of "Validator" actor:&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;reviewRequestTask&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;waitForUserTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;processInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;REVIEW_REQUEST_TASK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Take the task and execute it:&lt;/span&gt;
    &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assignAndExecuteUserTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reviewRequestTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;emptyMap&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c1"&gt;// If the request has been accepted, wait for the "Sign contract" task to be ready and execute it:&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;signContractTask&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;waitForUserTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initiator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;processInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SIGN_CONTRACT_TASK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assignAndExecuteUserTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initiator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signContractTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;emptyMap&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c1"&gt;// Wait for the whole process instance to finish executing:&lt;/span&gt;
    &lt;span class="nf"&gt;waitForProcessToFinish&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Instance of Process LoanRequest(1.0) with id ${processInstance.id} has finished executing."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Utility function to wait for a User task to be ready:&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;waitForUserTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;processInstanceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userTaskName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;HumanTaskInstance&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Awaitility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;await&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"User task should not last so long to be ready :-("&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;atMost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TEN_SECONDS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pollInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FIVE_HUNDRED_MILLISECONDS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getNumberOfPendingHumanTaskInstances&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1L&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getHumanTaskInstances&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processInstanceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userTaskName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Utility function to wait for a process to be completed:&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;waitForProcessToFinish&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Awaitility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;await&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Process instance lasts long to complete"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;atMost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TEN_SECONDS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pollInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FIVE_HUNDRED_MILLISECONDS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numberOfArchivedProcessInstances&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1L&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bonus: cherry on the top
&lt;/h3&gt;

&lt;p&gt;Spring Boot allows you to easily tune the banner that is displayed when an application starts.&lt;br&gt;
Simply put a &lt;code&gt;banner.txt&lt;/code&gt; file in the &lt;code&gt;resources&lt;/code&gt; folder with some ASCII art:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt; &lt;span class="n"&gt;_&lt;/span&gt;                        &lt;span class="n"&gt;______&lt;/span&gt;                           &lt;span class="n"&gt;_&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;                       &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;___&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;                         &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;     &lt;span class="n"&gt;___&lt;/span&gt;   &lt;span class="n"&gt;__&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="n"&gt;__&lt;/span&gt;   &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;___&lt;/span&gt;  &lt;span class="n"&gt;__&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;   &lt;span class="n"&gt;_&lt;/span&gt;  &lt;span class="n"&gt;___&lt;/span&gt;  &lt;span class="n"&gt;___&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;    &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;_`&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;  &lt;span class="p"&gt;|&lt;/span&gt;    &lt;span class="c1"&gt;// _ \/ _` | | | |/ _ \/ __| __|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;___&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;  &lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;
&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;_____&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;___&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;___&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;___&lt;/span&gt;&lt;span class="p"&gt;||&lt;/span&gt;&lt;span class="n"&gt;___&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
                                        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
                                        &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Expose business monitoring on our application flow
&lt;/h3&gt;

&lt;p&gt;Maybe we want our application to expose APIs to be able to follow the flow of our processes.&lt;br&gt;
Simply add the following Rest Controller class to expose the &lt;strong&gt;running&lt;/strong&gt; and &lt;strong&gt;completed&lt;/strong&gt; cases (process instances):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.bonitasoft.loanrequest.api&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.bonitasoft.engine.api.APIClient&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.GetMapping&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.RestController&lt;/span&gt;

&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CaseController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Expose the open process instances (=cases not completed)&lt;/span&gt;
    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/cases"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProcessInstance&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"install"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"install"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processAPI&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;searchOpenProcessInstances&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SearchOptionsBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Expose the finished process instances (=cases completed)&lt;/span&gt;
    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/completedcases"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;listCompleted&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ArchivedProcessInstance&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"install"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"install"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processAPI&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;searchArchivedProcessInstances&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SearchOptionsBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, to expose the tasks ready to execute, add the following Rest Controller class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.bonitasoft.loanrequest.api&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.PathVariable&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.RestController&lt;/span&gt;

&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TaskController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tasks"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;HumanTaskInstance&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"install"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"install"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;searchMyAvailableHumanTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;SearchOptionsBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;
        &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Full example
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/bonitasoft/bonita-examples/blob/master/bonita-loan-request-application/loan-request-app-gradle-kotlin/" rel="noopener noreferrer"&gt;This repository&lt;/a&gt; contains the full code of this example, ready to build / run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build your application
&lt;/h2&gt;

&lt;p&gt;Run &lt;code&gt;./gradlew build&lt;/code&gt; to build the binaries. It will generate a jar file in &lt;code&gt;build/libs/&lt;/code&gt; folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run your application
&lt;/h2&gt;

&lt;p&gt;Simply run the gradle command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./gradlew bootRun
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or run the previously-built jar file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; build/libs/bonita-loan-request-application.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then access the list of processes by opening a web browser at &lt;a href="http://localhost:8080/processes" rel="noopener noreferrer"&gt;http://localhost:8080/processes&lt;/a&gt;.&lt;br&gt;
The list of cases (process instances) is available at &lt;a href="http://localhost:8080/cases" rel="noopener noreferrer"&gt;http://localhost:8080/cases&lt;/a&gt;.&lt;br&gt;
The list of finished cases (completed process instances) is available at &lt;a href="http://localhost:8080/completedcases" rel="noopener noreferrer"&gt;http://localhost:8080/completedcases&lt;/a&gt;.&lt;br&gt;
The list of tasks is available at &lt;a href="http://localhost:8080/tasks" rel="noopener noreferrer"&gt;http://localhost:8080/tasks&lt;/a&gt;.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Configure the database
&lt;/h2&gt;

&lt;p&gt;When nothing is specified, an embedded H2 database is created and used.&lt;br&gt;
To use a different database, in folder &lt;code&gt;resources&lt;/code&gt; create a standard Spring Boot configuration file named &lt;code&gt;application.properties&lt;/code&gt; (or .yaml)&lt;br&gt;
and set the following properties. Here is an example with PostgreSQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# specify the database vendor you wish to use (supported values are h2, mysql, postgres, sqlserver, oracle):
&lt;/span&gt;&lt;span class="py"&gt;org.bonitasoft.engine.database.bonita.db-vendor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;postgres&lt;/span&gt;
&lt;span class="c"&gt;# specify the URL to connect to your database:
&lt;/span&gt;&lt;span class="py"&gt;org.bonitasoft.engine.database.bonita.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jdbc:postgresql://localhost:5432/bonita&lt;/span&gt;

&lt;span class="c"&gt;# specify the connection user to the database:
&lt;/span&gt;&lt;span class="py"&gt;org.bonitasoft.engine.database.bonita.user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;bonita&lt;/span&gt;
&lt;span class="c"&gt;# specify the connection password to the database:
&lt;/span&gt;&lt;span class="py"&gt;org.bonitasoft.engine.database.bonita.password&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;bpm&lt;/span&gt;
&lt;span class="py"&gt;org.bonitasoft.engine.database.bonita.datasource.maxPoolSize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;

&lt;span class="c"&gt;# specify a different AppServer port if required:
&lt;/span&gt;&lt;span class="py"&gt;server.port&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The provided &lt;code&gt;application.properties&lt;/code&gt; file contains examples for all database vendors.&lt;/p&gt;

&lt;p&gt;Finally, don't forget to replace the default H2 dependency for your PostgreSQL drivers in file &lt;code&gt;build.gradle.kts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// runtime("com.h2database:h2:1.4.199")&lt;/span&gt;
    &lt;span class="c1"&gt;// runtime("mysql:mysql-connector-java:8.0.14")&lt;/span&gt;
     &lt;span class="nf"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.postgresql:postgresql:42.2.5"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// runtime("com.microsoft.sqlserver:mssql-jdbc:7.2.1.jre8")&lt;/span&gt;
    &lt;span class="c1"&gt;// Oracle database drivers are not open-source and thus cannot be included here directly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>springboot</category>
      <category>bonita</category>
      <category>bpm</category>
      <category>workflow</category>
    </item>
    <item>
      <title>A self-managed developers' team experience: what it was like</title>
      <dc:creator>Emmanuel Duchastenier</dc:creator>
      <pubDate>Wed, 30 Jan 2019 08:59:47 +0000</pubDate>
      <link>https://dev.to/bonitasoft/a-self-managed-developers-team-experience-what-it-was-like-1hi5</link>
      <guid>https://dev.to/bonitasoft/a-self-managed-developers-team-experience-what-it-was-like-1hi5</guid>
      <description>&lt;p&gt;About a year ago, I had the opportunity to start a project with a team designated to  be self-managed by our manager. I enjoyed this way of working and I would like to share the advantages I appreciated.&lt;/p&gt;

&lt;p&gt;This article shares a specific way of working we used at Bonitasoft. However, I believe it is suitable reading to anyone interested in methodologies, whether Agile or not. I will sometimes talk about technical tools and technologies that developers are familiar with, but this is definitely not mandatory to understand my points here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;At Bonitasoft, our Continuous Integration environments (CI) were getting old: we were using Jenkins 2.0, configured with XML files under version control in a dedicated repository, which was separate from the repositories containing the source code to build and test.&lt;/p&gt;

&lt;p&gt;Maintaining those environments was laborious. Not all of our developers shared the necessary knowledge, and it was not possible to scale easily when we had parallel developments (because of the team’s growth, or because we were becoming more productive!)&lt;/p&gt;

&lt;p&gt;Five of us in the team really wanted to rewrite the whole thing from scratch, with newer tools and technologies.&lt;/p&gt;

&lt;p&gt;We took the opportunity to create a new project and experience a new way of organising ourselves, with a methodology &lt;strong&gt;by&lt;/strong&gt; developers, &lt;strong&gt;for&lt;/strong&gt; developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The advantages of self-management
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Autonomy is a mark of trust
&lt;/h3&gt;

&lt;p&gt;Our manager constantly seeks ways to keep developers engaged. He felt that leaving us as much freedom as possible to lead and carry out this project was a way of keeping us motivated.&lt;/p&gt;

&lt;p&gt;This did not mean we had no reviews to show other teams. On the contrary, every other week we had to demonstrate our progress, and most of the time, we were pretty proud of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Freedom to organise appropriately
&lt;/h3&gt;

&lt;p&gt;At Bonitasoft, we use Atlassian Jira to manage our tasks, support tickets, bugs, and more. We decided not to introduce a new tool for this project.&lt;/p&gt;

&lt;p&gt;However, we did decide to use a specific Jira Project (in the Jira meaning of “project”) for this initiative, with its specific workflow, that we deliberately chose to be light and non-restrictive. After all, our tools are here to serve us, not the contrary. We created our own dashboards to follow our progress.&lt;/p&gt;

&lt;p&gt;This allowed us to easily create as many tickets as we needed, delete them when necessary, resolve them, and close them, without the pain of having to fill in many fields that would not necessarily match our workflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1c8eovxk4x9r5f3eyb9e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1c8eovxk4x9r5f3eyb9e.png" alt="Our Kanban board with our lightweight workflow"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Our Kanban board with our lightweight workflow.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Freedom to choose our tools
&lt;/h3&gt;

&lt;p&gt;Rewriting a whole Continuous Integration environment for the entire R&amp;amp;D team is a lot of work, and choosing the right tools for the job was key. We took time for technological research. We investigated several tools, framework, ways of implementing security, means of writing proper Jenkins jobs / pipelines, and so on. We also became “experts” on Docker containers and their integration with tools like Gradle.&lt;/p&gt;

&lt;p&gt;The freedom - and responsibility - of choosing the proper technologies allowed us to train ourselves with some cutting-edge, current, trendy technologies. We also feel very proud of what we have achieved with these tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Everyone shares the same level of knowledge
&lt;/h3&gt;

&lt;p&gt;There was nothing revolutionary in the contribution workflow. Like everywhere else at Bonitasoft, contributions are made via basic Github Pull Request review workflow, very familiar to developers (not just at Bonitasoft, but pretty widely).&lt;/p&gt;

&lt;p&gt;Where we decided to innovate was to do our contribution reviews together as a group, and the decision to merge each Github Pull Request was agreed upon together as well. This might look like a strong constraint, but the benefit is huge: the main contributor gets the chance to explain the technology discovered, the difficulties encountered, why this implementation was considered the best option. The reviewers get the chance to ask questions, propose improvements - and discover new stuff.&lt;/p&gt;

&lt;p&gt;Merging a contribution was done when everyone agreed.&lt;/p&gt;

&lt;p&gt;If the contribution needed to be shared with developers in other teams, it was explained or demonstrated during the next advancement status, or in a dedicated technical talk, if appropriate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Freedom to be as involved as needed
&lt;/h3&gt;

&lt;p&gt;With five in the team, we had the option to shift our engagement, to have times to be more involved in developing the tasks we agreed to work on, and other times to pull back and just follow and review the developments made by others.&lt;/p&gt;

&lt;p&gt;This allowed us all to work according to our interests and individual schedules, and keep each other motivated by working on items we were really excited about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems encountered and how we managed them
&lt;/h2&gt;

&lt;p&gt;Keeping CI environments up-to-date and adapted to our evolving needs is a never-ending project.&lt;/p&gt;

&lt;p&gt;As with many long-term projects, keeping motivation up all the time is not easy. There were moments where little work was done from one week to the next, because the tasks were not the that interesting or exciting to work on, or because we were working on other concurrent priorities.&lt;/p&gt;

&lt;p&gt;However, having the option to be less involved from time to time, and then come back later with more enthusiasm to try new things allowed us to have a good overall delivery rate, as well as pride in the work we accomplished.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommendations for success with this approach
&lt;/h2&gt;

&lt;p&gt;Don’t stick with something you took that worked and seemed trendy at the time, but that does not fill the bill later on.&lt;/p&gt;

&lt;p&gt;For example, we tested and used a Jenkins plugin that allowed us to provision Docker containers on the fly. We were happy using it for a while. Then came the moment when when needed to use it at a larger scale, and we decided it was not the right tool for the job. So we simply changed to another implementation.&lt;/p&gt;

&lt;p&gt;My point here is that you shouldn’t hesitate to change, remove, or refactor something that you thought was exactly right 2 months earlier. Constant reassessment is normal in software development. It is ultimately more important to adapt the tool to the needs, than to preserve our pride.&lt;/p&gt;

&lt;p&gt;Here’s what I feel are key requirements for a successful team:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Self-managed team members should be able to choose to work together, not be selected by an outside person to create a team&lt;/li&gt;
&lt;li&gt;  Self-managed teams must accept that some team members will not be involved as much as others, and this is not a problem. In fact it can be an advantage.&lt;/li&gt;
&lt;li&gt;  Working as a self-managed team can only be successful if you have the full trust of your manager that you know what to do and how to work best together.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I have been working on a self-managed team for a year now, and I still am.&lt;/p&gt;

&lt;p&gt;It’s great to have had the chance to experience so much freedom.&lt;/p&gt;

&lt;p&gt;I’m  proud of the work I’ve been able to contribute on an individual level, and even more proud of the work we’ve done as a team.&lt;/p&gt;

&lt;p&gt;And technically, I have grown and learned a great deal through sharing with my coworkers.&lt;/p&gt;

&lt;p&gt;I recommend every developer who loves what they do to try working in a self-managed team - try it if you can and see how it works for you.&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>creating</category>
      <category>softwareengineering</category>
      <category>methodology</category>
    </item>
  </channel>
</rss>
