<?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: Aurimas Dainius</title>
    <description>The latest articles on DEV Community by Aurimas Dainius (@ragutislt).</description>
    <link>https://dev.to/ragutislt</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%2Fuser%2Fprofile_image%2F2533985%2F70453766-754c-41bc-b473-a1d86179cb26.jpeg</url>
      <title>DEV Community: Aurimas Dainius</title>
      <link>https://dev.to/ragutislt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ragutislt"/>
    <language>en</language>
    <item>
      <title>Architecture Decision Records</title>
      <dc:creator>Aurimas Dainius</dc:creator>
      <pubDate>Mon, 19 May 2025 07:24:20 +0000</pubDate>
      <link>https://dev.to/ragutislt/architecture-decision-records-3c5h</link>
      <guid>https://dev.to/ragutislt/architecture-decision-records-3c5h</guid>
      <description>&lt;p&gt;"Why did we choose this framework again?" - a question heard too often in development teams.&lt;/p&gt;

&lt;p&gt;When working on complex projects, architectural decisions can quickly be forgotten or misunderstood.&lt;/p&gt;

&lt;p&gt;Even decisions made just months ago can become unclear without proper documentation.&lt;/p&gt;

&lt;p&gt;Archtecture Decision Records, or ADRs solve this problem by capturing the context and consequences of architectural choices. Each record documents:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The specific architectural decision.&lt;/li&gt;
&lt;li&gt;The context and the problems it addresses.&lt;/li&gt;
&lt;li&gt;The consequences and trade-offs considered.&lt;/li&gt;
&lt;li&gt;The current status of the decision.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I've found ADRs particularly valuable when onboarding new team members or revisiting old projects.&lt;/p&gt;

&lt;p&gt;They provide clear insights into why certain choices were made and help prevent the same discussions from happening repeatedly.&lt;/p&gt;

&lt;p&gt;The best part about ADRs is their simplicity. A basic template, version control, and consistent updates are all you need.&lt;/p&gt;

&lt;p&gt;They don't require complex tools or extensive documentation processes.&lt;/p&gt;

&lt;p&gt;💡 While ADRs might seem like extra work initially, they can save a team countless hours of discussions and prevent many misunderstandings about architectural choices.&lt;/p&gt;

&lt;p&gt;If you're not using ADRs yet, I strongly recommend trying them out.&lt;/p&gt;

&lt;p&gt;Your future self (or your colleagues) will thank you. 📝&lt;/p&gt;

&lt;p&gt;&lt;a href="https://adr.github.io/ad-practices/" rel="noopener noreferrer"&gt;https://adr.github.io/ad-practices/&lt;/a&gt; is a nice resource that gathers info from multiple different sources. Great if you'd like to learn more.&lt;br&gt;
Otherwise, just registering the 4 key info points listed above is enough to get started.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>architecture</category>
      <category>programming</category>
    </item>
    <item>
      <title>How can you make sure you are implementing the right software?</title>
      <dc:creator>Aurimas Dainius</dc:creator>
      <pubDate>Tue, 29 Apr 2025 12:17:17 +0000</pubDate>
      <link>https://dev.to/ragutislt/how-can-you-make-sure-you-are-implementing-the-right-software-30eb</link>
      <guid>https://dev.to/ragutislt/how-can-you-make-sure-you-are-implementing-the-right-software-30eb</guid>
      <description>&lt;p&gt;I've found one of the best ways is to use Domain-Driven Design (DDD) - a software development approach that emphasizes close collaboration between business and developers through a common language that both can understand.&lt;/p&gt;

&lt;p&gt;Here are the main benefits of DDD:&lt;br&gt;
1️⃣ Shared Language: Using ubiquitous language eliminates translation between business and technical terms. Practically this means not using terminology in your business logic code that a business person would not be able to understand.&lt;br&gt;
2️⃣ Business-Centric Models: DDD forces developers to model software around business concepts.&lt;br&gt;
3️⃣ Clear Boundaries: Defining bounded contexts helps organize large systems into manageable pieces and identify parts that can become their own product or identify non-core domains that can be bought elsewhere instead of developing in-house.&lt;/p&gt;

&lt;p&gt;However, DDD is not mainstream at all in the software community, in a large part I think due to deeply-engrained organizational practices that create silos between devs and business.&lt;/p&gt;

&lt;p&gt;The real value of DDD isn't in its technical patterns but in how it structures communication.&lt;/p&gt;

&lt;p&gt;When business stakeholders can read your business logic code and understand the behaviour, you're probably on the right track.&lt;/p&gt;

&lt;p&gt;Two great books to learn more:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215" rel="noopener noreferrer"&gt;Domain-Driven Design: Tackling Complexity in the Heart of Software&lt;/a&gt; by Eric Evans, the author of DDD. This is more of an all-rounder introduction.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/0321834577/ref=sr_1_1?crid=P5MNAAER5AKK&amp;amp;dib=eyJ2IjoiMSJ9.MzKi7vDEDQ-l8DULwhs0Q5bVpPagm8OAOTOW0tjJYa8OlWNosikAxHthbt-G5zbK1SEQMhev1J979BU8HLRuOubnphXgCdrxgqw_SlZSrNm2ZlXbjwPkvULF0e9afMY2I9L3cd4zvEjbOZcv3MS7c7ebBJIXMBkMHZqypHRCchpTLHiDBnwiNQzzCM30Iep82ihtturA9J3KBhB8bAAkHXFHvp9Jdvse91Sb-yhowYU.I1cnCkbgyuCNnLMaQuHgbuIhdskxHYxuht7-PM_MPPc&amp;amp;dib_tag=se&amp;amp;keywords=vaughn+vernon&amp;amp;qid=1745928915&amp;amp;s=books&amp;amp;sprefix=vaughn+vernon%2Cstripbooks-intl-ship%2C286&amp;amp;sr=1-1" rel="noopener noreferrer"&gt;Implementing Domain-Driven Design&lt;/a&gt; by Vaughn Vernon. This is more of a practical guide with many code samples and patterns.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>ddd</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why do software projects fail despite having excellent code?</title>
      <dc:creator>Aurimas Dainius</dc:creator>
      <pubDate>Thu, 24 Apr 2025 06:58:39 +0000</pubDate>
      <link>https://dev.to/ragutislt/why-do-software-projects-fail-despite-having-excellent-code-104h</link>
      <guid>https://dev.to/ragutislt/why-do-software-projects-fail-despite-having-excellent-code-104h</guid>
      <description>&lt;p&gt;It's concerning how many developers obsess over code quality while missing the fundamental question: are we building what users actually need? &lt;/p&gt;

&lt;p&gt;Most of us have seen projects where teams spent weeks perfecting their architecture, choosing the latest frameworks, and arguing over the smallest of details on a pull request - only to deliver features that users never use. 🚫 This happens because we often jump straight into implementation without properly understanding the business requirements.&lt;/p&gt;

&lt;p&gt;Here's a typical scenario:&lt;br&gt;
Developer: "I've implemented a complex caching system to improve performance by X%" &lt;br&gt;
User: "But I need the system to handle multiple currencies, not faster loading times" &lt;/p&gt;

&lt;p&gt;The solution?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start with workshops with BOTH your business and devs. 🤝&lt;/li&gt;
&lt;li&gt;Use techniques like Event Storming or Domain Storytelling to make sure everyone is on the same page. 📝&lt;/li&gt;
&lt;li&gt;Implement a system with 0 latency feedback loops - anyone should be able to send a screenshot to the business and ask their take. 🔄&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Typically, teams spend a tiny minority of the whole project time on the things above, whereas it should take a good chunk of total project time.&lt;/p&gt;

&lt;p&gt;Technical excellence matters, but it should come after ensuring we're building the right solution. &lt;/p&gt;

&lt;p&gt;Final food for thought: A perfectly coded wrong solution is still wrong. 🤷‍♂️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>discuss</category>
      <category>product</category>
    </item>
    <item>
      <title>Developers should have been replaced a long time ago. 🤔</title>
      <dc:creator>Aurimas Dainius</dc:creator>
      <pubDate>Tue, 15 Apr 2025 06:55:43 +0000</pubDate>
      <link>https://dev.to/ragutislt/developers-should-have-been-replaced-a-long-time-ago-49pj</link>
      <guid>https://dev.to/ragutislt/developers-should-have-been-replaced-a-long-time-ago-49pj</guid>
      <description>&lt;p&gt;Or at least this was widely believed when each big innovation came out.&lt;br&gt;
&lt;a href="https://strategizeyourcareer.com/p/the-10-times-in-history-that-software" rel="noopener noreferrer"&gt;The fantastic article&lt;/a&gt; lists 10 such waves that should have replaced us, including:&lt;br&gt;
1️⃣ High level languages.&lt;br&gt;
2️⃣ The Internet.&lt;br&gt;
3️⃣ Low-code/No-code.&lt;/p&gt;

&lt;p&gt;Each of them changed development, even in my 10-year career I've lived through several such waves, and the number of software developers in the world kept increasing regardless.&lt;/p&gt;

&lt;p&gt;GenAI is the current wave. We see big claims (mostly from CTOs and business managers) about AI replacing developers. It makes sense for them to increase the hype, as they care about cost savings.&lt;/p&gt;

&lt;p&gt;Developers care about usability though, and when AI tools become advanced enough to accelerate development and all the processes involved (requirements, testing, documentation, architecture, etc...), more and more software will be produced, therefore increasing demand for developers.&lt;/p&gt;

&lt;p&gt;The best way to prepare for such shifts rests the same as it has always been - continuous learning, not staying too long in the comfort zone, and making everyone around you better. 📈 📖&lt;/p&gt;

</description>
      <category>ai</category>
      <category>development</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>From Code to Cloud: A Deep Dive into Mendix Deployments - Part 3: Private Cloud</title>
      <dc:creator>Aurimas Dainius</dc:creator>
      <pubDate>Tue, 01 Apr 2025 10:37:19 +0000</pubDate>
      <link>https://dev.to/ragutislt/from-code-to-cloud-a-deep-dive-into-mendix-deployments-part-3-private-cloud-450j</link>
      <guid>https://dev.to/ragutislt/from-code-to-cloud-a-deep-dive-into-mendix-deployments-part-3-private-cloud-450j</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/ragutislt/from-code-to-cloud-a-deep-dive-into-mendix-deployments-part-1-1ch9"&gt;1st part of the series&lt;/a&gt; we have presented the various ways you can deploy a Mendix application. If you haven't read it yet, it will be a good primer for the whole series.&lt;/p&gt;

&lt;p&gt;In this article we'll explore Private Cloud deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Private Cloud?
&lt;/h2&gt;

&lt;p&gt;Private Cloud means using cloud-native technologies (e.g. Docker, Kubernetes) on an infrastructure that you control.&lt;br&gt;
It does not have to be physically on your servers, but you need access to create and remove resources.&lt;/p&gt;

&lt;p&gt;For the purposes of Mendix, this will mean a Kubernetes or OpenShift cluster provided by one of the supported providers.&lt;/p&gt;

&lt;p&gt;The Kubernetes pod you deploy will contain what was described in &lt;a href="https://dev.to/ragutislt/from-code-to-cloud-a-deep-dive-into-mendix-deployments-part-2-on-premise-3h80#mendix-application-dissected"&gt;the on-premise overview article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tfcyj3ft3t28el7avpr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tfcyj3ft3t28el7avpr.png" alt="Private Cloud" width="800" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the image above, you can see that you have a lot of control with Private Cloud. &lt;br&gt;
Let's list some advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can decide where to physically host your cluster.&lt;/li&gt;
&lt;li&gt;You decide how it will be accessed.&lt;/li&gt;
&lt;li&gt;Control how deployments will work.&lt;/li&gt;
&lt;li&gt;Decide your security constraints, how to protect it from outside threats.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Naturally, there are drawbacks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You need to have the hardware to host your cluster.&lt;/li&gt;
&lt;li&gt;You need to have the know-how of how to configure all of that.&lt;/li&gt;
&lt;li&gt;You need to implement security, load-balancing, deployments, ci/cd, etc...&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Whether it's right for you will depend on many organizational, technical, functional constraints. If you haven't decided yet, check out the &lt;a href="https://dev.to/ragutislt/from-code-to-cloud-a-deep-dive-into-mendix-deployments-part-1-1ch9"&gt;previous blog post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are actually 2 &lt;em&gt;versions&lt;/em&gt; of the Private Cloud.&lt;/p&gt;
&lt;h3&gt;
  
  
  Connected mode
&lt;/h3&gt;

&lt;p&gt;In connected mode, you can manage many aspects of your app through the &lt;a href="https://privatecloud.mendixcloud.com/" rel="noopener noreferrer"&gt;Mendix Portal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For example: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change constants' values.&lt;/li&gt;
&lt;li&gt;Add JVM arguments.&lt;/li&gt;
&lt;li&gt;Increase the nr of replicas of your app.&lt;/li&gt;
&lt;li&gt;Change the admin password.&lt;/li&gt;
&lt;li&gt;Change log levels.&lt;/li&gt;
&lt;li&gt;etc...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpdnav27g51nkbrrpd50r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpdnav27g51nkbrrpd50r.png" alt="Connected Mode control panel" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One caveat here is that you will need to whitelist some urls from your cluster so that Mendix (the &lt;em&gt;gateway agent&lt;/em&gt; specifically) can communicate with its external portal and vice-versa. &lt;a href="https://docs.mendix.com/developerportal/deploy/private-cloud-cluster/#prerequisites-connected" rel="noopener noreferrer"&gt;Details here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Standalone mode
&lt;/h3&gt;

&lt;p&gt;In standalone mode, you only interact with your cluster directly, you don't have any &lt;em&gt;control panel&lt;/em&gt; to manage it through the Mendix Portal.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to deploy
&lt;/h2&gt;

&lt;p&gt;There are a few steps to this process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Register a new cluster in the Mendix Portal.&lt;/li&gt;
&lt;li&gt;Add a namespace where you will deploy your app.&lt;/li&gt;
&lt;li&gt;Install the mendix operator inside your namespace.&lt;/li&gt;
&lt;li&gt;Deploy your app into that cluster and namespace.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Register a new cluster
&lt;/h3&gt;

&lt;p&gt;This does not mean actually creating the cluster in Kubernetes. You must create a cluster yourself in whichever K8s (or OpenShift) provider and then just tell the Mendix Portal that it exists.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn35ky1werbqgq60agt9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn35ky1werbqgq60agt9g.png" alt="Registering a new cluster" width="670" height="987"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Add a namespace
&lt;/h3&gt;

&lt;p&gt;Next you need to register a namespace where your app will live.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4yl263g4uy2bn12s819x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4yl263g4uy2bn12s819x.png" alt="Registering a new namespace" width="676" height="369"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Install the Mendix operator
&lt;/h3&gt;

&lt;p&gt;Once you've done with the cluster registration, you will get a link to download the Mendix operator.&lt;/p&gt;
&lt;h4&gt;
  
  
  Mendix operator
&lt;/h4&gt;

&lt;p&gt;This operator is a separate pod that runs in your namespace. It is a &lt;a href="https://kubernetes.io/docs/concepts/extend-kubernetes/operator/" rel="noopener noreferrer"&gt;Kubernetes Operator&lt;/a&gt; that monitors pod/pods of your Mendix app. &lt;/p&gt;

&lt;p&gt;Whenever you update something through the Mendix Portal (a jvm argument, the app version, etc...), the operator receives this new information and applies the necessary changes to your app's pod.&lt;/p&gt;

&lt;p&gt;The operator itself can be configured with the &lt;code&gt;mxpc-cli&lt;/code&gt; script. This script produces a yaml file with &lt;a href="https://docs.mendix.com/developerportal/deploy/private-cloud-technical-appendix-01/#custom-resources" rel="noopener noreferrer"&gt;custom resources&lt;/a&gt; which contain the operator's configuration.&lt;/p&gt;

&lt;p&gt;To install it, you'll run a command like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mxpc-cli installer &lt;span class="nt"&gt;-n&lt;/span&gt; &amp;lt;your namespace&amp;gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &amp;lt;namespace uid&amp;gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &amp;lt;secret&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed you can either use the non-interactive mode and configure it via commands, or use the interactive mode and configure it using a UI&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0kgdcc8uik0rh962k4q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0kgdcc8uik0rh962k4q.png" alt="mxpc-cli UI" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This utility also allows you to do other things, here's the help message from it:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkm4kicg66q109dh9jda4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkm4kicg66q109dh9jda4.png" alt="mxpc-cli script options" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once configured, the operator will establish a connection to your database, storage, registry to confirm that the configuration is correct.&lt;/p&gt;

&lt;p&gt;The configuration of the operator and your app is saved in custom K8S resources: &lt;em&gt;OperatorConfiguration&lt;/em&gt;, &lt;em&gt;MendixApp&lt;/em&gt;, ...&lt;/p&gt;

&lt;p&gt;You can of course inspect them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get OperatorConfiguration &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-oyaml&lt;/span&gt; | less
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;privatecloud.mendix.com/v1alpha1&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;OperatorConfiguration&lt;/span&gt;
  &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mendix-operator-configuration&lt;/span&gt;
    &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;baseOSImageTagTemplate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubi8-1-jre{{.JavaVersion}}-entrypoint&lt;/span&gt;
    &lt;span class="na"&gt;buildResources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;256Mi&lt;/span&gt;
      &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;250m&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;64Mi&lt;/span&gt;
    &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;nginx.ingress.kubernetes.io/proxy-body-size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;500m&lt;/span&gt;
        &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.49.2.nip.io&lt;/span&gt;
        &lt;span class="na"&gt;enableTLS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;ingressClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;public&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/*&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ingress&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means you could also save this yaml in your gitops repository, version it, template it, and use for future deployments even without the &lt;em&gt;mxpc-cli&lt;/em&gt; utility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy the app
&lt;/h3&gt;

&lt;p&gt;Now you can finally deploy your app to this cluster. You need to go to your app's page in the Mendix Portal, the environments section.&lt;/p&gt;

&lt;p&gt;You need to create the environment. This allows you to create environments that are &lt;em&gt;connected&lt;/em&gt; with different namespaces or even different clusters.&lt;/p&gt;

&lt;p&gt;Once created, just deploy your app to that cluster.&lt;/p&gt;

&lt;p&gt;The following will happen next:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Mendix operator will receive the instructions to deploy the app.&lt;/li&gt;
&lt;li&gt;It's going to start a worker pod to build a docker image of your app.&lt;/li&gt;
&lt;li&gt;It will launch a pod based on the image produced just before.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You will then be able to see your app's releases and all configured environments from this page:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs8kdei7pzx1qjqxa5g35.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs8kdei7pzx1qjqxa5g35.png" alt="Private cloud app environments" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This page allows you to deploy a release to the environment of your choosing. Typically, you will have at least a &lt;em&gt;dev&lt;/em&gt; and a &lt;em&gt;production&lt;/em&gt; environment, but you can adapt it to your needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supported providers
&lt;/h2&gt;

&lt;p&gt;As of 01 Apr 2025, the &lt;a href="https://docs.mendix.com/developerportal/deploy/private-cloud-supported-environments/#kubernetes-cluster-types" rel="noopener noreferrer"&gt;following&lt;/a&gt; providers or &lt;em&gt;flavours&lt;/em&gt; of k8s are supported.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This was not meant to be a full guide on how to do a private-cloud deployment, as there is too much information to cover in just one article. Instead, it's meant to give an overview of what it means, what you can do with it, and why you would want to deploy to a private cloud in the first place.&lt;br&gt;
For a guide with more instructions I would still refer to the official &lt;a href="https://docs.mendix.com/developerportal/deploy/private-cloud-cluster/" rel="noopener noreferrer"&gt;Mendix documentation&lt;/a&gt; but know that sometimes it's not easy to understand everything written there, from my experience.&lt;/p&gt;

&lt;p&gt;Hopefully this gives you more information and motivation to use it with your Mendix applications.&lt;br&gt;
I will do separate articles on more detailed subjects, like: difference between connected and standalone environments, how to segregate your environments from each other, more details on the mendix operator, how to integrate a CI/CD pipeline, etc...&lt;/p&gt;

&lt;p&gt;If you'd like more information, or need some help in setting up your deployments, don't hesitate to reach out.&lt;/p&gt;

</description>
      <category>mendix</category>
      <category>cloud</category>
      <category>kubernetes</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>From Code to Cloud: A Deep Dive into Mendix Deployments - Part 2: On-Premise</title>
      <dc:creator>Aurimas Dainius</dc:creator>
      <pubDate>Thu, 20 Mar 2025 09:41:36 +0000</pubDate>
      <link>https://dev.to/ragutislt/from-code-to-cloud-a-deep-dive-into-mendix-deployments-part-2-on-premise-3h80</link>
      <guid>https://dev.to/ragutislt/from-code-to-cloud-a-deep-dive-into-mendix-deployments-part-2-on-premise-3h80</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/ragutislt/from-code-to-cloud-a-deep-dive-into-mendix-deployments-part-1-1ch9"&gt;1st part of the series&lt;/a&gt; we have presented the various ways you can deploy a Mendix application. If you haven't read it yet, it will be a good primer for the whole series.&lt;/p&gt;

&lt;p&gt;We'll start by exploring on-premise deployments.&lt;/p&gt;

&lt;p&gt;Why on-premise first?&lt;/p&gt;

&lt;p&gt;Mainly it's because on-premise is the lowest level we can go to, meaning the web server and application level. This can help us learn what building blocks the application is made of and what it actually &lt;em&gt;is&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does on-premise mean?
&lt;/h2&gt;

&lt;p&gt;An essential question to answer. With Mendix, you can consider on-premise any deployment on your own infrastructure that is generally not running Kubernetes or OpenShift &lt;em&gt;and&lt;/em&gt; not using a &lt;a href="https://docs.mendix.com/developerportal/deploy/private-cloud-technical-appendix-01/" rel="noopener noreferrer"&gt;Mendix Operator&lt;/a&gt;.&lt;br&gt;
If you use them, we'd be talking about a &lt;em&gt;Private Cloud&lt;/em&gt; deployment.&lt;/p&gt;

&lt;p&gt;More on this later.&lt;/p&gt;
&lt;h2&gt;
  
  
  Mendix application dissected
&lt;/h2&gt;

&lt;p&gt;To be able to deploy a Mendix application, it will be good for us to understand the technology behind.&lt;/p&gt;

&lt;p&gt;Mendix applications are based on JVM: when you click 'Run' in Mendix Studio Pro, it will collect all the microflows, constants, even entities, and build them into an executable java application. (how that's done is interesting as well but it's better to leave that for another article)&lt;/p&gt;

&lt;p&gt;This application can then be run as any other java application would be.&lt;br&gt;
If we were to &lt;code&gt;ssh&lt;/code&gt; into a Mendix application pod (or just a docker container), you'd see exactly a java process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /proc/29/cmdline
/opt/mendix/build/.local/bin/java &lt;span class="nt"&gt;-Dfile&lt;/span&gt;.encoding&lt;span class="o"&gt;=&lt;/span&gt;UTF-8 &lt;span class="nt"&gt;-Djava&lt;/span&gt;.io.tmpdir&lt;span class="o"&gt;=&lt;/span&gt;/opt/mendix/build/data/tmp &lt;span class="nt"&gt;-XX&lt;/span&gt;:OnError&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; USR1 7 &lt;span class="nt"&gt;-XX&lt;/span&gt;:OnOutOfMemoryError&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; USR2 7 &lt;span class="nt"&gt;-DapplicationName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;docker_example &lt;span class="nt"&gt;-XX&lt;/span&gt;:MaxMetaspaceSize&lt;span class="o"&gt;=&lt;/span&gt;256M &lt;span class="nt"&gt;-Xmx512M&lt;/span&gt; &lt;span class="nt"&gt;-Xms512M&lt;/span&gt; &lt;span class="nt"&gt;-XX&lt;/span&gt;:+UseSerialGC &lt;span class="nt"&gt;-DMX_INSTALL_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/mendix/build/runtimes/10.20.0.60519 &lt;span class="nt"&gt;-jar&lt;/span&gt; /opt/mendix/build/runtimes/10.20.0.60519/runtime/launcher/runtimelauncher.jar /opt/mendix/build/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last argument &lt;code&gt;/opt/mendix/build/&lt;/code&gt; of the command contains our whole application on the container (example app below called NoTicket):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /opt/mendix/build/web/pages/en_US/NoTicket/
Ticket_NewEdit.page.xml      Ticket_NewEdit.page.xml.gz   Ticket_Overview.page.xml     Ticket_Overview.page.xml.gz

&lt;span class="nb"&gt;ls&lt;/span&gt; /opt/mendix/build/model/
bundles/           dependencies.json  i18n/              lib/               metadata.json      microflows.json    model.mdp          operations.json    resources/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From this we can learn that it's basically a jar of the mendix runtime that &lt;code&gt;runs&lt;/code&gt; a folder which contains our application's compiled code (the jvm bytecode) and the resources it needs (.js, .css files, pages in .xml format, etc...). When you build your app, it is packaged into an &lt;em&gt;.mda&lt;/em&gt; file which is basically an archive of your application.&lt;/p&gt;

&lt;p&gt;Does that sound familiar? If you're coming from Java EE (or Jakarta EE) background, this might make you think immediately of an application server like Tomcat.&lt;/p&gt;

&lt;p&gt;And you would be right, &lt;a href="https://www.mendix.com/evaluation-guide/enterprise-capabilities/architecture/runtime-architecture/" rel="noopener noreferrer"&gt;Mendix Runtime&lt;/a&gt; is actually an &lt;em&gt;equivalent&lt;/em&gt; of an application server like Tomcat. Here's a representation on what it contains:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4alfqs1h1wvud4lz1di.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4alfqs1h1wvud4lz1di.png" alt="Mendix Runtime" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The HTTP server you see in the image uses Jetty as a library to handle http requests but it does not itself implement the Jakarta Servlet API. Hence, you cannot build a mendix application and deploy on a Tomcat, or deploy any other Java application on a Mendix Runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to deploy on premise
&lt;/h2&gt;

&lt;p&gt;We have a few options to deploy on premise:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Deploy on Linux as a Java process using &lt;a href="https://github.com/mendix/m2ee-tools/blob/develop/doc/install-1.md" rel="noopener noreferrer"&gt;m2ee-tools&lt;/a&gt; python utility.&lt;/li&gt;
&lt;li&gt;Deploy on a &lt;a href="https://docs.mendix.com/developerportal/deploy/deploy-mendix-on-microsoft-windows/" rel="noopener noreferrer"&gt;Microsoft IIS server&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Deploy wherever you want using Docker (best solution in my view).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mendix prides itself on being cloud-native out-of-the-box, and we should benefit from that as much as possible. While you can containerize any application in theory, with Mendix that's already taken care of - just build your image and deploy.&lt;br&gt;
Therefore, I will only focus on the last option, using Docker. It has many advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It's better both for you and your system admin as you can isolate your app's environment from the machine it's running on.&lt;/li&gt;
&lt;li&gt;It bundles the app into a neat package that can be run on any machine.&lt;/li&gt;
&lt;li&gt;It's easy to split the &lt;em&gt;build&lt;/em&gt; and &lt;em&gt;deploy&lt;/em&gt; processes.&lt;/li&gt;
&lt;li&gt;Devs can modify the image to include any supporting processes in the container.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To build the app, we will use &lt;a href="https://github.com/mendix/docker-mendix-buildpack" rel="noopener noreferrer"&gt;docker-mendix-buildpack&lt;/a&gt;. It will collect your application files, produce an &lt;em&gt;.mda&lt;/em&gt; package, and build a docker image.&lt;/p&gt;

&lt;p&gt;You can follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone docker-mendix-buildpack:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/mendix/docker-mendix-buildpack
&lt;span class="nb"&gt;cd &lt;/span&gt;docker-mendix-buildpack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Clone your app's repo where you want to build it (you can get the git link from the &lt;em&gt;Team Server&lt;/em&gt; section of your app in Mendix Portal):
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://git.api.mendix.com/xxxx-yyyy-zzzz-yyyy.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Build your image:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;BUILD_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;appFolder &lt;span class="nt"&gt;--tag&lt;/span&gt; mendix/mendix-appName:deploy &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;On the 1st run, it's going to build some helper images, so it will take some time. On next runs it's going to be much faster.&lt;br&gt;
Once you've done that, you can either run the image, or push it to your company's container registry if you have a different build and runtime server.&lt;br&gt;
If it's a release version, make sure to give it a version (like 1.1.0 instead of a snapshot version like &lt;em&gt;deploy&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;To start it, simply run the docker image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;ADMIN_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Password1! &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;DATABASE_ENDPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres://username:password@host:port/mendix &lt;span class="se"&gt;\&lt;/span&gt;
  mendix/mendix-appName:deploy  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How you can use it as part of you CI/CD process
&lt;/h2&gt;

&lt;p&gt;You can easily automate the process with a simple bash script, integrate into a build tool like Jenkins, or Github Actions, Gitlab Workflows, etc...&lt;/p&gt;

&lt;h3&gt;
  
  
  docker compose
&lt;/h3&gt;

&lt;p&gt;I also like to use docker-compose to quickly deploy a database alongside the app container. This way I can build and deploy a fully-functioning app in minutes. &lt;br&gt;
Here's a sample script for reference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.0"&lt;/span&gt;
&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mendix-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;shm_size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;128mb&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mendix&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mendix&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres-db:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mendix-network&lt;/span&gt;
  &lt;span class="na"&gt;mendix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mendix/mendix-appName:deploy&lt;/span&gt;
    &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appName&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appName&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080:8080"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;ADMIN_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;some&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;great&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;password"&lt;/span&gt;
      &lt;span class="na"&gt;DATABASE_ENDPOINT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres://mendix:postgres@postgres:5432/mendix&lt;/span&gt;
      &lt;span class="na"&gt;mem_limit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;500m&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mendix-network&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres-db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
docker logs appName &lt;span class="nt"&gt;--follow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Kubernetes
&lt;/h3&gt;

&lt;p&gt;Technically, once you have build a docker image (or an image in OCI format), you can just run it in your kubernetes cluster. Normally with Mendix though, you would use a &lt;a href="https://docs.mendix.com/developerportal/deploy/private-cloud-technical-appendix-01/" rel="noopener noreferrer"&gt;Mendix Operator&lt;/a&gt; which would build the app and the image for you and start your app. This would all take place inside your cluster. It will be covered much more in depth in an upcoming article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Mendix makes it easy to deploy cloud-native applications on your infrastructure. Using the &lt;a href="https://github.com/mendix/docker-mendix-buildpack" rel="noopener noreferrer"&gt;docker-mendix-buildpack&lt;/a&gt; you can easily produce a docker image with your application, and deploy it wherever you want.&lt;/p&gt;

&lt;p&gt;While on-premise deployments are not always the best option, they can be great for small applications, demos, proof of concepts, or if the client's infrastructure does not support Kubernetes or OpenShift deployments.&lt;/p&gt;

&lt;p&gt;Hopefully, this information will help you understand the behind-the-scenes processes of a Mendix app build and deployment, aiding in debugging any deployment issues regardless of the chosen deployment option.&lt;br&gt;
If you'd like more information, or need some help in setting up your deployments, don't hesitate to reach out.&lt;/p&gt;

</description>
      <category>mendix</category>
      <category>lowcode</category>
      <category>cloud</category>
      <category>java</category>
    </item>
    <item>
      <title>From Code to Cloud: A Deep Dive into Mendix Deployments - Part 1</title>
      <dc:creator>Aurimas Dainius</dc:creator>
      <pubDate>Mon, 24 Feb 2025 13:44:21 +0000</pubDate>
      <link>https://dev.to/ragutislt/from-code-to-cloud-a-deep-dive-into-mendix-deployments-part-1-1ch9</link>
      <guid>https://dev.to/ragutislt/from-code-to-cloud-a-deep-dive-into-mendix-deployments-part-1-1ch9</guid>
      <description>&lt;p&gt;This article will begin a multiple-part series on Mendix deployments. Building applications quickly and easily with Mendix is awesome, but those applications eventually need to run on some hardware.&lt;/p&gt;

&lt;p&gt;We're going to see how much flexibility Mendix provides based on your unique needs and capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment options
&lt;/h2&gt;

&lt;p&gt;With Mendix, you have 3 main options for deploying your applications.&lt;br&gt;
Here they are ordered by convenience and amount of control:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllftqdwhxxj4k16exc4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllftqdwhxxj4k16exc4g.png" alt="Mendix Deployment Options" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see from the very professional image above, Mendix Cloud is the most convenient option, but offers the least control.&lt;/p&gt;

&lt;p&gt;On-premise deployments, on the other end, offer least convenience, but allow for extreme levels of control.&lt;/p&gt;

&lt;p&gt;Let's quickly recap each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mendix Cloud
&lt;/h2&gt;

&lt;p&gt;The easiest option. You must estimate how many resources your app is going to need, and select a &lt;a href="https://docs.mendix.com/developerportal/deploy/mendix-cloud-deploy/#resource-pack" rel="noopener noreferrer"&gt;cloud resource pack&lt;/a&gt; suitable for your needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2n38fr15agqsdnavxg4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2n38fr15agqsdnavxg4b.png" alt="Mendix Cloud Deployment" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mostly everything then will be setup for you as you can see in the simplified image above.&lt;/p&gt;

&lt;p&gt;With this option, you have the following advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ease of setup. Select your resource pack and deploy.&lt;/li&gt;
&lt;li&gt;Out-of-the box tools for your app's lifecycle: monitoring, auditing, firewall, backups, etc...&lt;/li&gt;
&lt;li&gt;Ensured availability based on your subscription plan.&lt;/li&gt;
&lt;li&gt;You can choose the region where you want your app to be hosted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are some drawbacks (if you can call them that):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cost. This is an obvious one - if you don't host your application, it has to be hosted somewhere, so you must pay for those resources.
However, cost is a complex subject, you need to evaluate a lot of criteria, like what skills your team possesses (and their cost in turn), how much time you're willing to spend on the operational part (which costs too), etc...&lt;/li&gt;
&lt;li&gt;You have less control over the application. This is logical - if you run something on your server, you can customize it any way you want. 
With a public cloud, you have much fewer options.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Mendix Private Cloud
&lt;/h2&gt;

&lt;p&gt;Private Cloud means you host your mendix application on cloud resources that you own and directly pay for.&lt;br&gt;
This can be a kubernetes cluster on a cloud provider like AWS, Google Cloud Platform, or Azure.&lt;/p&gt;

&lt;p&gt;It can also mean a kubernetes cluster on a local instance of MicroK8s, Kind, or any other local kubernetes setup.&lt;/p&gt;

&lt;p&gt;You also have the option to deploy an app on an OpenShift cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frf9c52qyjiosozwhd57u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frf9c52qyjiosozwhd57u.png" alt="Mendix Private Cloud Deployment" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Private Cloud is great if your organization already has a cluster that you can use, or have strict compliance and security standards which might restrict you from using any publicly-provided Cloud setups that you don't control yourself.&lt;/p&gt;

&lt;p&gt;With Private Cloud, you are free to choose your own provider, implement your own security policies, setup your own monitoring, backup, other tools.&lt;/p&gt;

&lt;p&gt;Cost is likely to be lower, especially if you have a skilled DevOps team who can install the mendix app in your cluster, configure the needed tools, and maintain it in the long run.&lt;/p&gt;

&lt;h2&gt;
  
  
  On-premise
&lt;/h2&gt;

&lt;p&gt;Lastly we have on-premise deployments.&lt;br&gt;
On-premise is the old school 'it works on my machine' way.&lt;/p&gt;

&lt;p&gt;In practice, you would probably have a bare metal server inside your company or provided by a hosting provider.&lt;br&gt;
You'd run a mendix app either as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A java process directly on the server.&lt;/li&gt;
&lt;li&gt;A process inside a MS Internet Information Services (IIS) server.&lt;/li&gt;
&lt;li&gt;A docker container on your server.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Obviously, if you have to go the on-premise way, I'd go with docker for better isolation of both your app and your server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjorvscdtyrda28zrw9d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjorvscdtyrda28zrw9d.png" alt="Mendix On-Premise Deployment" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With these deployments you will certainly have the most control, but also the most hassle as you'll have to setup everything yourself.&lt;/p&gt;

&lt;p&gt;For some small use cases where you don't need a kubernetes cluster but you can't use the Mendix Cloud due to compliance/security constraints, this will be the only option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Mendix provides a lot of flexibility on how to deploy your application. When you have to make a decision, consult their in-depth &lt;a href="https://www.mendix.com/evaluation-guide/deployment/flexibility/decision-guide/" rel="noopener noreferrer"&gt;decision guide&lt;/a&gt; to make the best decision for your use case.&lt;br&gt;
You'll have to take many elements into account - regulatory, security circumstances you have, the technical skills and composition of your team, your current DevOps maturity, your budget, etc...&lt;/p&gt;

&lt;p&gt;If you'd like to learn more, head over to the Mendix documentation and stay tuned for upcoming articles. Each of these deployment options will get a deep dive of its own in the next weeks.&lt;/p&gt;

</description>
      <category>mendix</category>
      <category>lowcode</category>
      <category>cloud</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>Converting a Spring MVC App To Mendix</title>
      <dc:creator>Aurimas Dainius</dc:creator>
      <pubDate>Wed, 05 Feb 2025 18:28:03 +0000</pubDate>
      <link>https://dev.to/ragutislt/converting-a-spring-mvc-app-to-mendix-36pc</link>
      <guid>https://dev.to/ragutislt/converting-a-spring-mvc-app-to-mendix-36pc</guid>
      <description>&lt;p&gt;This is a followup to &lt;a href="https://dev.to/ragutislt/converting-jpa-entities-to-mendix-502a"&gt;this post about JPA entity export from Java to Mendix&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Last time we saw how, given a Java Spring application, we can read it's metadata and 'recreate' it in a Mendix application. We detected JPA entities (based on &lt;code&gt;@Entity&lt;/code&gt; annotation), exported them to a custom json schema, and finally imported everything to Mendix using their &lt;a href="https://docs.mendix.com/apidocs-mxsdk/mxsdk/" rel="noopener noreferrer"&gt;Platform SDK&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now we're going to see how to convert another essential part of a Java Spring app - the REST layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample Spring MVC app
&lt;/h2&gt;

&lt;p&gt;Our sample uses the Spring MVC framework, but similar logic could be applied to Jersey or any other framework.&lt;/p&gt;

&lt;p&gt;It has only one controller: the &lt;code&gt;CatController&lt;/code&gt; (what did you think it was going to be? :P)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/cat"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;consumes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;produces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CatController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;CatService&lt;/span&gt; &lt;span class="n"&gt;catService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CatController&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CatService&lt;/span&gt; &lt;span class="n"&gt;catService&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;catService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;catService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CatDto&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;allCats&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;catService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCats&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The controller is exposed under path &lt;code&gt;/cat&lt;/code&gt; and it produces json when called with GET. It will return a list of all cats in our database.&lt;/p&gt;

&lt;p&gt;Here are the objects we will have to convert between Java and Mendix:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Spring MVC application -&amp;gt; would be a published REST service in Mendix.&lt;/li&gt;
&lt;li&gt;Spring MVC controller -&amp;gt; a resource in a published REST service.&lt;/li&gt;
&lt;li&gt;A method corresponding to a REST endpoint -&amp;gt; an operation in a Mendix resource.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Extracting controllers into json
&lt;/h2&gt;

&lt;p&gt;Same as in the last article, we will be using reflection to detect controllers and api endpoints at runtime. You can see other possible alternatives pondered in the &lt;a href="https://dev.to/ragutislt/converting-jpa-entities-to-mendix-502a#extracting-entity-metadata-in-json"&gt;last post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's the code that gathers all this info:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;exportRESTLayerTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;AnnotatedTypeScanner&lt;/span&gt; &lt;span class="n"&gt;typeScanner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AnnotatedTypeScanner&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RestController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;restControllerClasses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;typeScanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findTypes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JavaToMendixApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPackageName&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Controller classes are: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;restControllerClasses&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MendixPublishedRestService&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mendixRestServices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MendixPublishedRestServiceResource&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mendixResources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;restControllerClass&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;restControllerClasses&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MendixPublishedRestServiceOperation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mendixOperations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Method&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;restControllerClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDeclaredMethods&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isPublic&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getModifiers&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MendixPublishedRestServiceOperation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;restOperation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;findRestOperation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAnnotations&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="n"&gt;restOperation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ifPresent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mendixOperations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;MendixPublishedRestServiceResource&lt;/span&gt; &lt;span class="n"&gt;newResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MendixPublishedRestServiceResource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;retrieveControllerPath&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;restControllerClass&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;mendixOperations&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;mendixResources&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newResource&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We begin by finding all classes annotated with &lt;code&gt;@RestController&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, for each controller, we:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the path specified in the &lt;code&gt;path&lt;/code&gt; field of the annotation. This path will also become the name of the mendix resource.&lt;/li&gt;
&lt;li&gt;We will then retrieve controller methods that correspond to our endpoints.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To find the right controller methods, we just need to pick public methods and check if their annotations correspond to any of the following Spring MVC endpoint annotations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;,&lt;/span&gt; &lt;span class="nc"&gt;RestOperation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;JAVA_TO_MENDIX_REST_OPERATION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofEntries&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GetMapping&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RestOperation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GET&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PostMapping&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RestOperation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;POST&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PutMapping&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RestOperation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PUT&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DeleteMapping&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RestOperation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DELETE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For each such endpoint method we find, we will add it to the list of operations in the &lt;code&gt;MendixPublishedRestServiceResource&lt;/code&gt; object.&lt;br&gt;
For simplicity's sake we only do a basic mapping of the endpoints, but we could go deeper and also export path params, request body, headers, etc...&lt;/p&gt;

&lt;p&gt;Finally, we create a &lt;code&gt;MendixPublishedRestService&lt;/code&gt; object to contain our rest controller and export to a json file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;mendixRestServices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MendixPublishedRestService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"JavaToMendixApplication"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"api"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mendixResources&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;writeToJsonFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mendixRestServices&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are all the classes we used for the export:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;MendixPublishedRestService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MendixPublishedRestServiceResource&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;MendixPublishedRestServiceResource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MendixPublishedRestServiceOperation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;operations&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;MendixPublishedRestServiceOperation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
    &lt;span class="nc"&gt;RestOperation&lt;/span&gt; &lt;span class="n"&gt;restOperation&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;RestOperation&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;GET&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;POST&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;PUT&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;DELETE&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Importing rest services into Mendix
&lt;/h2&gt;

&lt;p&gt;Now we're going to use Mendix's &lt;a href="https://docs.mendix.com/apidocs-mxsdk/mxsdk/" rel="noopener noreferrer"&gt;Platform SDK&lt;/a&gt; which has a Typescript API to interact with it.&lt;/p&gt;

&lt;p&gt;First we'll create some objects to represent our services and controllers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ImportedRestService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImportedRestResource&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ImportedRestResource&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;operations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImportedRestOperation&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ImportedRestOperation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;restOperation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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 we are going to create a working copy of our Mendix app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MendixPlatformClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;workingCopy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTemporaryWorkingCopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;workingCopy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allModules&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MyFirstModule&lt;/span&gt;&lt;span class="dl"&gt;"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SDK will actually pull our mendix app from git and work on that.&lt;/p&gt;

&lt;p&gt;After reading from the json file, we will loop the services.&lt;/p&gt;

&lt;p&gt;First we create a &lt;code&gt;PublishedRestService&lt;/code&gt; first in our &lt;code&gt;MyFirstModule&lt;/code&gt; module.&lt;br&gt;
We give it a name, version, and base path (in our case, &lt;code&gt;api&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;importedServices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;importedService&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;restService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PublishedRestService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;restService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serviceName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;importedService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;restService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;importedService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;restService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;importedService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;restService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;importedService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serviceName&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;We then loop the resources in that service and create a &lt;code&gt;PublishedRestServiceResource&lt;/code&gt; with a name (which will also be a path for that resource):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;importedService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;importedResource&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publishedRestResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PublishedRestServiceResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;restService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;publishedRestResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;importedResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;Finally, we get the operations for each resource. Operations could have their own path, which will be appended to the service and resource path. We also assign an http method and create a sample microflow for that operation so that we have something to work with once the import is complete:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;importedResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;operations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;op&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publishedRestOperation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PublishedRestServiceOperation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;publishedRestResource&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;publishedRestOperation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;op&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;publishedRestOperation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;httpMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getMendixHttpMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;op&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;restOperation&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;assignSampleMicroflowToOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;importedResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;op&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publishedRestOperation&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 Mendix Platform SDK will create the service in its local working copy of our mendix application. Now we just need to tell it to commit the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;commitChanges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;workingCopy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OnlineWorkingCopy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entitiesFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;servicesFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flushChanges&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;workingCopy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commitToRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;commitMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Imported DB entities from &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;entitiesFile&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; and REST services from &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;servicesFile&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;After a few seconds, you can open the app in Mendix Studio Pro and verify the results:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feswjef25og0w2paed733.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feswjef25og0w2paed733.png" alt="Generated mendix rest service" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our published rest service has been created and we can start working on the microflows behind each endpoint.&lt;/p&gt;

&lt;p&gt;If you'd like to experiment yourself or see the full code, head over to &lt;a href="https://github.com/ragutislt/mendix-exporter-from-java-demo/tree/main" rel="noopener noreferrer"&gt;this repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ideas for the future
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Improve documentation of the Mendix Platform SDK. There is a lack of user guides and often documentation on what various objects represent. My last articles were meant to mitigate this issue.&lt;/li&gt;
&lt;li&gt;The examples are in Java but the same concepts can be applied for any language.&lt;/li&gt;
&lt;li&gt;One day I'll make a full library out of this and try to use static code analysis instead of runtime analysis to 'export' the Java app as it will be more convenient for the user.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.mendix.com/apidocs-mxsdk/mxsdk/" rel="noopener noreferrer"&gt;Mendix Platform SDK&lt;/a&gt; is a powerful feature allowing to interact with the mendix app programmatically. We can export entire apps to mendix, although the business logic part will require more effort.&lt;/p&gt;

&lt;p&gt;Mendix list some &lt;a href="https://docs.mendix.com/apidocs-mxsdk/mxsdk/sdk-use-cases/" rel="noopener noreferrer"&gt;sample use cases&lt;/a&gt; like importing/exporting code, analyzing app complexity, etc...&lt;/p&gt;

&lt;p&gt;Have a look at them in case you are interested.&lt;/p&gt;

&lt;p&gt;For this article, you can find the full code &lt;a href="https://github.com/ragutislt/mendix-exporter-from-java-demo/tree/main" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>mendix</category>
      <category>java</category>
      <category>spring</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>Converting JPA entities to Mendix</title>
      <dc:creator>Aurimas Dainius</dc:creator>
      <pubDate>Mon, 13 Jan 2025 08:07:28 +0000</pubDate>
      <link>https://dev.to/ragutislt/converting-jpa-entities-to-mendix-502a</link>
      <guid>https://dev.to/ragutislt/converting-jpa-entities-to-mendix-502a</guid>
      <description>&lt;p&gt;Recently while exploring Mendix, I've noticed they had a &lt;a href="https://docs.mendix.com/apidocs-mxsdk/mxsdk/" rel="noopener noreferrer"&gt;Platform SDK&lt;/a&gt; which allows you to interact with the mendix app model through an API.&lt;/p&gt;

&lt;p&gt;This gave me an idea to explore if it can be used to create our domain model. Specifically, to create a domain model based on an existing traditional application.&lt;/p&gt;

&lt;p&gt;If generalized further, this could be used to convert any existing application into Mendix and continue development from there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Converting a Java/Spring web application to Mendix
&lt;/h2&gt;

&lt;p&gt;So, I created a small Java/Spring web application with a simple API and database layer. It uses an embedded H2 database for simplicity.&lt;/p&gt;

&lt;p&gt;In this post, we are only going to be converting JPA entities. Let's take a look at them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="nd"&gt;@Table&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"CAT"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Cat&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="nd"&gt;@GeneratedValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenerationType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AUTO&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@OneToOne&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Human&lt;/span&gt; &lt;span class="n"&gt;humanPuppet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;getters&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="nd"&gt;@Table&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HUMAN"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Human&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="nd"&gt;@GeneratedValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenerationType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AUTO&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;getters&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see they are quite simple: a &lt;code&gt;Cat&lt;/code&gt; with a name, age, color, and its &lt;code&gt;Human&lt;/code&gt; puppet, since cats rule the world as we know.&lt;/p&gt;

&lt;p&gt;Both of them have an auto-generated ID field. &lt;code&gt;Cat&lt;/code&gt; has a one-to-one association with a Human so that it can call its human whenever it wants. (If it wasn't a JPA entity I would have put a &lt;code&gt;meow()&lt;/code&gt; method but let's leave that for the future).&lt;/p&gt;

&lt;p&gt;The app is fully functioning but right now we're only interested in the data layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extracting Entity metadata in json
&lt;/h2&gt;

&lt;p&gt;This can be done in a few different ways: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;By statically analyzing entities in their package.&lt;/li&gt;
&lt;li&gt;By using reflection to read those entities at runtime.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I've opted for option 2 because it's quicker and I couldn't easily find a library that can do option 1.&lt;/p&gt;

&lt;p&gt;Next, we need to decide how to expose json once we build it. To make things simple, we'll just write it into a file. Some alternative ways could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exposing it through an api. This is more complicated as you also need to ensure that endpoint is secured very well as we must not expose our metadata publicly.&lt;/li&gt;
&lt;li&gt;Exposing it through some management tool, like spring boot actuator, or jmx. It's safer, but still takes time to setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's now see the actual code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MendixExporter&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;exportEntitiesTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;AnnotatedTypeScanner&lt;/span&gt; &lt;span class="n"&gt;typeScanner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AnnotatedTypeScanner&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Entity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;entityClasses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;typeScanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findTypes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JavaToMendixApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPackageName&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Entity classes are: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entityClasses&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MendixEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mendixEntities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;entityClass&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entityClasses&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MendixAttribute&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Field&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entityClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDeclaredFields&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                &lt;span class="nc"&gt;AttributeType&lt;/span&gt; &lt;span class="n"&gt;attributeType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;determineAttributeType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="nc"&gt;AssociationType&lt;/span&gt; &lt;span class="n"&gt;associationType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;determineAssociationType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attributeType&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;associationEntityType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;determineAssociationEntityType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attributeType&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

                &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MendixAttribute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;attributeType&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;associationType&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;associationEntityType&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="nc"&gt;MendixEntity&lt;/span&gt; &lt;span class="n"&gt;newEntity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MendixEntity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entityClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSimpleName&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;mendixEntities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newEntity&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;writeToJsonFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mendixEntities&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We start with finding all classes in our app marked with JPA's &lt;code&gt;@Entity&lt;/code&gt; annotation.&lt;br&gt;
Then, for each class, we:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the declared fields with &lt;code&gt;entityClass.getDeclaredFields()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Loop each field of that class.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For each field then, we:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Determine the attribute's type:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;,&lt;/span&gt; &lt;span class="nc"&gt;AttributeType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;JAVA_TO_MENDIX_TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofEntries&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AttributeType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;STRING&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AttributeType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INTEGER&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// we return AttributeType.ENTITY if we cannot map to anything else&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Essentially we just match the java type with our custom enum values by looking them up in &lt;code&gt;JAVA_TO_MENDIX_TYPE&lt;/code&gt; map.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Next, we check if this attribute is actually an association (points to another &lt;code&gt;@Entity&lt;/code&gt;). If so, we determine the type of an association it is: one-to-one, one-to-many, many-to-many:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;AssociationType&lt;/span&gt; &lt;span class="nf"&gt;determineAssociationType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Field&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AttributeType&lt;/span&gt; &lt;span class="n"&gt;attributeType&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;attributeType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AttributeType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ENTITY&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getType&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;AssociationType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ONE_TO_MANY&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;AssociationType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ONE_TO_ONE&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;To do that, we just check the previously mapped attribute type. In case it's &lt;code&gt;Entity&lt;/code&gt;, which just means that in the step before we couldn't map it to any primitive java type, String, or Enum.&lt;br&gt;
Then we also need to decide what kind of association it is. The check is simple: if it's a &lt;code&gt;List&lt;/code&gt; type, then it's a one-to-many, otherwise one-to-one (did not implement 'many-to-many' yet).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We then create a &lt;code&gt;MendixAttribute&lt;/code&gt; object for each field found.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once that is done, we just create a &lt;code&gt;MendixEntity&lt;/code&gt; object for the entity with a list of attributes assigned.&lt;br&gt;
&lt;code&gt;MendixEntity&lt;/code&gt; and &lt;code&gt;MendixAttribute&lt;/code&gt; are classes we will use to map to json later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;MendixEntity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MendixAttribute&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;MendixAttribute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;AttributeType&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;AssociationType&lt;/span&gt; &lt;span class="n"&gt;associationType&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;entityType&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;AttributeType&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;STRING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;INTEGER&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;DECIMAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;AUTO_NUMBER&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;BOOLEAN&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;ENUM&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;ENTITY&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;AssociationType&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;ONE_TO_ONE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;ONE_TO_MANY&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we save a &lt;code&gt;List&amp;lt;MendixEntity&amp;gt;&lt;/code&gt; to a json file using jackson.&lt;/p&gt;

&lt;h2&gt;
  
  
  Importing entities into Mendix
&lt;/h2&gt;

&lt;p&gt;Here comes the fun part, how do we read the json file we generated above and create mendix entities from it?&lt;/p&gt;

&lt;p&gt;Mendix's &lt;a href="https://docs.mendix.com/apidocs-mxsdk/mxsdk/" rel="noopener noreferrer"&gt;Platform SDK&lt;/a&gt; has a Typescript API to interact with it.&lt;br&gt;
First we will create objects to represent our entities and attributes, as well as enums for association and attribute types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ImportedEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;generalization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImportedAttribute&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ImportedAttribute&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImportedAttributeType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;entityType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;associationType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImportedAssociationType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;ImportedAssociationType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ONE_TO_ONE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ONE_TO_ONE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;ONE_TO_MANY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ONE_TO_MANY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;ImportedAttributeType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;INTEGER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INTEGER&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;STRING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;STRING&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;DECIMAL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DECIMAL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;AUTO_NUMBER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AUTO_NUMBER&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;BOOLEAN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BOOLEAN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;ENUM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ENUM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;ENTITY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ENTITY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to get our app with an appId, create a temporary working copy, open the model, and find the domain model we are interested in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MendixPlatformClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;workingCopy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTemporaryWorkingCopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;workingCopy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;domainModelInterface&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allDomainModels&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dm&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;containerAsModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;MyFirstModule&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;)[0];
const domainModel = await domainModelInterface.load();
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SDK will actually pull our mendix app from git and work on that.&lt;/p&gt;

&lt;p&gt;After reading from the json file, we will loop the entities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createMendixEntities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;domainModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;domainmodels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DomainModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entitiesInJson&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;importedEntities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImportedEntity&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entitiesInJson&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;importedEntities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;importedEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mendixEntity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;domainmodels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;domainModel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;mendixEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;importedEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nf"&gt;processAttributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;importedEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mendixEntity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;importedEntities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;importedEntity&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mendixParentEntity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;domainModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;importedEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;domainmodels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;processAssociations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;importedEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;domainModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mendixParentEntity&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;Here we use &lt;code&gt;domainmodels.Entity.createIn(domainModel);&lt;/code&gt; to create a new entity in our domain model and assign a name to it. We can assign more properties, like documentation, indexes, even location where the entity will be rendered in the domain model.&lt;/p&gt;

&lt;p&gt;We process the attributes in a separate function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processAttributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;importedEntity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImportedEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mendixEntity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;domainmodels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;importedEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;ImportedAttributeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ENTITY&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mendixAttribute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;domainmodels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Attribute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mendixEntity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;mendixAttribute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getAttributeName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;importedEntity&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nx"&gt;mendixAttribute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;assignAttributeType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mendixAttribute&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;The only thing here we have to put some effort in is to map the attribute type to a valid mendix type.&lt;/p&gt;

&lt;p&gt;Next we process the associations. Firstly, since in our Java entities associations were declared by a field, we need to distinguish which fields are simple attributes, and which are associations. To do that we just need to check if it's an &lt;code&gt;ENTITY&lt;/code&gt; type or a primitive type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;importedEntity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ImportedAttributeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ENTITY&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 create the associations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mendixAssociation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;domainmodels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Association&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;domainModel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mendixChildEntity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;domainModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entityType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;domainmodelsEntity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;mendixAssociation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mendixParentEntity&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mendixChildEntity&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;mendixAssociation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mendixParentEntity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;mendixAssociation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mendixChildEntity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;mendixAssociation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;associationType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ImportedAssociationType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ONE_TO_ONE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;associationType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ImportedAssociationType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ONE_TO_MANY&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;
    &lt;span class="nx"&gt;domainmodels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AssociationType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Reference&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;domainmodels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AssociationType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReferenceSet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;mendixAssocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;associationType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ImportedAssociationType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ONE_TO_ONE&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;domainmodelsAssociationOwner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Both&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;domainmodels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AssociationOwner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have 4 important properties to set, besides the name:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The parent entity. This is the current entity.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The child entity. In the last step, we created mendix entities for each java entity. Now we just need to find the matching entity based on the type of the java field in our entity:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;domainModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entityType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;domainmodelsEntity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Association type. If it's one-to-one, it maps to a &lt;code&gt;Reference&lt;/code&gt;. If it's one-to-many, it maps to a &lt;code&gt;Reference Set&lt;/code&gt;. We will skip many-to-many for now.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The association owner. Both one-to-one and many-to-many associations have the same owner type: &lt;code&gt;Both&lt;/code&gt;. For one-to-one, the owner type must be &lt;code&gt;Default&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Mendix Platform SDK will have created the entities in its local working copy of our mendix application. Now we just need to tell it to commit the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;commitChanges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;workingCopy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OnlineWorkingCopy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entitiesFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flushChanges&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;workingCopy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commitToRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;commitMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Imported DB entities from &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;entitiesFile&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;After a few seconds, you can open the app in Mendix Studio Pro and verify the results:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7rxf3m3pejp7tapw1y5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7rxf3m3pejp7tapw1y5.png" alt="Generated mendix domain model" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There you have it: a &lt;code&gt;Cat&lt;/code&gt; and &lt;code&gt;Human&lt;/code&gt; entity with a one-to-one association in between them.&lt;/p&gt;

&lt;p&gt;If you'd like to experiment yourself or see the full code, head over to &lt;a href="https://github.com/ragutislt/mendix-exporter-from-java-demo/tree/main" rel="noopener noreferrer"&gt;this repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ideas for the future
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In this example I've used a Java/Spring application to convert from since I'm most proficient in it but any application can be used. 
It's enough to just be able to read type data (statically or at runtime) to extract the class and field names.&lt;/li&gt;
&lt;li&gt;I'm curious to try reading and exporting some java logic to Mendix microflows. We probably can't really convert the business logic itself but we should be able to get the structure of it (business method signatures at least?).&lt;/li&gt;
&lt;li&gt;The code from this article could be generalized and made into a library: the json format can stay the same, and there could be one library to export java types, and another one to import mendix entities.&lt;/li&gt;
&lt;li&gt;We could use the same approach to do the reverse: convert a mendix to another language.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.mendix.com/apidocs-mxsdk/mxsdk/" rel="noopener noreferrer"&gt;Mendix Platform SDK&lt;/a&gt; is a powerful feature allowing to interact with the mendix app programmatically. They list some &lt;a href="https://docs.mendix.com/apidocs-mxsdk/mxsdk/sdk-use-cases/" rel="noopener noreferrer"&gt;sample use cases&lt;/a&gt; like importing/exporting code, analyzing app complexity.&lt;br&gt;
Have a look at them in case you are interested.&lt;br&gt;
For this article, you can find the full code &lt;a href="https://github.com/ragutislt/mendix-exporter-from-java-demo/tree/main" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>mendix</category>
      <category>lowcode</category>
      <category>java</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Collaborating with business using low-code development</title>
      <dc:creator>Aurimas Dainius</dc:creator>
      <pubDate>Thu, 19 Dec 2024 10:40:20 +0000</pubDate>
      <link>https://dev.to/ragutislt/collaborating-with-business-using-low-code-development-fp3</link>
      <guid>https://dev.to/ragutislt/collaborating-with-business-using-low-code-development-fp3</guid>
      <description>&lt;p&gt;Has it ever happened to you while coding that you either had to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Draw a diagram before starting coding to put ideas into place and have a scheme of how a process should look like?&lt;/li&gt;
&lt;li&gt;Have to draw a diagram to show to a business stakeholder so that you are able to more easily explain how a process works?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I bet you've faced at least one of those situations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lost in translation
&lt;/h2&gt;

&lt;p&gt;There are a few problems caused by such scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The biggest one is that some information will inevitably be lost in translation. Some information will be lost in the intermediate step of drawing a diagram, whether you plan to write code from it later or you draw it based on existing code.&lt;/li&gt;
&lt;li&gt;It takes time and energy to make a more visual model of what needs to be done.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How low-code can help
&lt;/h2&gt;

&lt;p&gt;One of the biggest advantages of low-code development is &lt;em&gt;visual programming&lt;/em&gt; where instead of writing text you drag and drop or draw elements that eventually do something you expect.&lt;/p&gt;

&lt;p&gt;Let's consider the example below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd03abdk2ch99knboihmp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd03abdk2ch99knboihmp.png" alt="A simple business microflow in Mendix" width="800" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Are you able to deduce what is done in this flow? (called &lt;em&gt;microflow&lt;/em&gt; in &lt;a href="https://www.mendix.com/" rel="noopener noreferrer"&gt;Mendix&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;I would argue even a non-technical person will understand the gist of it.&lt;/p&gt;

&lt;p&gt;We get the following benefits of visual programming in this case:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Both you and the more business-oriented person (but anyone can benefit from this really) will have a much more intuitive representation of a business process. And it's an actual piece of software that runs and is constantly evolving, not some document that stays hidden away in Confluence and eventually becomes obsolete.&lt;/li&gt;
&lt;li&gt;It's quicker as we can understand drawings much faster than we can read text. &lt;/li&gt;
&lt;li&gt;It's shared because the other person, even if they don't have a lot of technical skills, will be able to figure out more or less what they are seeing. It can also be used in meetings/presentations.&lt;/li&gt;
&lt;li&gt;Less information will be lost in translation as there are simply fewer steps for information to travel.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are some drawbacks too:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Poorly implemented microflows would still be difficult to understand.&lt;/li&gt;
&lt;li&gt;Some training is still needed. Any visual programming tool still has a &lt;em&gt;notation&lt;/em&gt; which, even if simple, requires at least minimal investment to understand.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;It's a simple use case, but stacked up over time, over many interactions can add up to significantly less time used for such activities and likely producing better results due to less friction in knowledge sharing.&lt;/p&gt;

&lt;p&gt;You still need to follow good programming practices with low-code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Avoid microflows with too much stuff in it. Just like in normal programming, code that executes business logic should be quite clear to read and not overloaded with technical calls.&lt;/li&gt;
&lt;li&gt;Don't be afraid of long variable/object names. This is descriptive and most of the time avoids the need for comments, which tend to not be updated as logic changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As low-code tooling continues to evolve, I feel like the gap between developer and business knowledge will grow ever smaller, benefiting everyone involved.&lt;/p&gt;

</description>
      <category>mendix</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>Getting used to visual software development</title>
      <dc:creator>Aurimas Dainius</dc:creator>
      <pubDate>Tue, 10 Dec 2024 20:36:39 +0000</pubDate>
      <link>https://dev.to/ragutislt/getting-used-to-visual-software-development-9ip</link>
      <guid>https://dev.to/ragutislt/getting-used-to-visual-software-development-9ip</guid>
      <description>&lt;p&gt;Recently I've started using a low-code platform &lt;a href="https://www.mendix.com/" rel="noopener noreferrer"&gt;Mendix&lt;/a&gt; to produce software.&lt;br&gt;
I wasn't planning on it, but an opportunity presented itself and I was curious to learn more about this new (to me) thing.&lt;/p&gt;

&lt;p&gt;And, to my surprise, I did like it.&lt;br&gt;
Probably the biggest change is passing from writing actual lines of code in text, to visually constructing the software.&lt;/p&gt;

&lt;p&gt;For UI, this is not weird at all, it's even much more pleasant than writing HTML/CSS/JavaScript.&lt;br&gt;
For backend though, it's a different story.&lt;/p&gt;
&lt;h2&gt;
  
  
  How does it actually work?
&lt;/h2&gt;

&lt;p&gt;Think about this: when you need to code something complex, you normally don't start writing code right away.&lt;br&gt;
You think about it, draw something down on a whiteboard or a piece of paper, identify some patterns, and only then start coding.&lt;/p&gt;

&lt;p&gt;With Mendix, the process feels very similar, except that the last 'coding' part is very different.&lt;/p&gt;

&lt;p&gt;Here's how the process looks like in Mendix:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You create a new &lt;em&gt;microflow&lt;/em&gt;. Microflows are where your business logic gets executed. I like to think of them as a method in a service class. You can call other microflows from within.&lt;/li&gt;
&lt;li&gt;You drag and drop which elements you need to implement your logic. You will do the same things as you would in Java: create variables, retrieve stuff from the database, modify objects, loop collections, have conditional statements, etc...&lt;/li&gt;
&lt;li&gt;At the end of the microflow, you might return something, or not return anything. You might commit an object to the DB, or signal to the client-side that a page should be closed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here are some &lt;em&gt;activities&lt;/em&gt; you can add to a mendix microflow:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbo9hkb8ik43e14rjng76.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbo9hkb8ik43e14rjng76.png" alt="microflow activities" width="800" height="835"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are many more of them and you can even create your own. &lt;br&gt;
There are hundreds more in the mendix marketplace to choose from.&lt;/p&gt;

&lt;p&gt;And here's a sample microflow:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1hjccwma8pyjqh6g91a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1hjccwma8pyjqh6g91a.png" alt="Sample microflow" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we simply retrieve an object from the database or create a new one if it doesn't exist.&lt;br&gt;
It's quite neat and easy-to-understand, even for a non-technical person.&lt;/p&gt;

&lt;p&gt;It could look something like this in Java:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SubscriptionService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;SubscriptionCost&lt;/span&gt; &lt;span class="nf"&gt;getOrCreateSubscriptionCost&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Subscription&lt;/span&gt; &lt;span class="n"&gt;subscription&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;BillingFrequency&lt;/span&gt; &lt;span class="n"&gt;billingFrequency&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// implement getSubscriptionCost method somewhere, or use a spring data repository&lt;/span&gt;
        &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SubscriptionCost&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;existingCost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subscriptionRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSubscriptionCost&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;billingFrequency&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;subscription&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;existingCost&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orElseGet&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;SubscriptionCost&lt;/span&gt; &lt;span class="n"&gt;newCost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SubscriptionCost&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subscription&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;billingFrequency&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...);&lt;/span&gt;
            &lt;span class="n"&gt;subscriptionRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newCost&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;newCost&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;});&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They are both good, and both are visualizations of a process that happens in the real world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros of visual development
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;You have a visual representation of the flow you are modelling, making things clearer without having to do drawings yourself without writing code.&lt;/li&gt;
&lt;li&gt;The visual representation is the actual 'code', no need to convert it to something else yourself.&lt;/li&gt;
&lt;li&gt;You can literally show the microflow to a business person and they are much more likely to understand drawings rather than code.&lt;/li&gt;
&lt;li&gt;It is a much better documentation than just code.&lt;/li&gt;
&lt;li&gt;You are likely to move faster. This is simply due to the fact that you are operating at a higher level of abstraction. If the flexibility of your platform is enough for you, you will be faster. If not, you might be blocked and have to spend time implementing code yourself to accomplish what you need.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Cons of visual development
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;As it is still an abstraction over regular code, inevitably you do lose some flexibility, same as what happens when passing from assembly to C or from C to Java.&lt;/li&gt;
&lt;li&gt;Given that the 'visual' model needs to be translated to machine-runnable code, it will be slower to run. (though I suspect there are many optimizations in Mendix to make it as fast as possible)&lt;/li&gt;
&lt;li&gt;As of 2024, low-code community is not that big compared to the big programming languages, so you might not get help soon if you need it.
For Mendix, there is the Mendix forum and the marketplace, where you can find many third-party addons, but apart from that there is not much else.&lt;/li&gt;
&lt;li&gt;It might be easier to do static code analysis. 
This depends on the low-code platform. With some, if there is no textual representation of the flow, it will be more difficult to develop tools that analyse it. (this might change with AI but it will take time)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;To summarize, visual development is an alternative way to write software. It might feel more natural to many people, can be shared with non-technical people for demonstration purposes, and can help developers to put complex ideas in a more clear mannter.&lt;/p&gt;

&lt;p&gt;That being said, traditional code development is not going anywhere and still has advantages of performance and flexibility.&lt;/p&gt;

&lt;p&gt;If you are in a position to choose one or the other, consider the pros and cons above and think about factors such as flexibility, performance, ease of development, what skillsets you currently possess.&lt;/p&gt;

&lt;p&gt;This way you will find the best approach for you.&lt;/p&gt;

</description>
      <category>mendix</category>
      <category>lowcode</category>
      <category>java</category>
    </item>
  </channel>
</rss>
