My journey with Mendix started more than four years ago. Due to the nature of my Mendix projects many times I had to use third-party java libraries and based on that experience two years ago I wrote a blog post on Managing java Dependencies for Mendix Modules. Since then, I have gained more insight into this process and wanted to share it with you.
So the goal of this blog post is to document my learnings and best practices for adding a java library to a Mendix project and see how they can be applied in a practical example.
Excited? Let's go!
In my opinion, the best way to add a third party dependency to Mendix is to first set up a separate pure java project (using gradle or maven) that includes the dependency and provides an easy-to-use interface. Then use a shadow plugin to generate a so-called fat jar that contains all dependencies and import that to your Mendix project.
This is to an extent the same message from my previous blog post. However, as you will see from the list below by doing things slightly differently, the list of benefits to using this approach can be greatly expanded. Here is a list of advantages of using the above process:
- Automatically deal with transitive dependencies.
Almost every java library has other java libraries it depends on. Downloading them one by one is cumbersome, error-prone and not maintainable. Gradle and maven both support dependency management out of the box. They will find and download the right dependencies for the library that you plan to use. Also, because all dependencies are in one jar, any dependencies that are no longer needed are automatically removed on build, thus making for an easy update process unlike so many Mendix modules where developers are asked to manually delete unused or old dependencies when upgrading.
- Avoid version conflicts for transitive dependencies.
Unfortunately, Mendix java class loader which is based on OSGI does not handle multiple versions of a dependency. This can be a blocking issue if the library you are trying to use needs to load a specific version of a dependency while Mendix runtime or another Mendix module is using a different version of the same dependency. Thanks to the shadow plugin such dependencies can be shadowed thus enabling the class loader to load them at the same time.
- Get to know the java library in isolation.
Using a third party library that you are not familiar with is hard enough on its own. Trying to do it in the context of a large Mendix project is a thousand times harder. If something does not work it is impossible to say if the error comes from the library, your java code, the integration between Mendix and java or the Mendix app itself. Also testing and debugging is more complicated and time-consuming when you have to start a Mendix runtime every time.
- Code to the interface that you want.
Many times the java library will have a complicated interface to use. This is java after all so in order to do something as simple as a function call you will probably need to go through the usual list of suspects: factories, builders and managers until you have an object that you can actually call the method on. It is best to hide this complexity away and build a simple adapter/facade that has the interface that you want and need. An added bonus is that you can swap out the third-party library for another without having to touch the Mendix application.
- Easily set up unit tests that serve as a regression suite.
This is so important I would like to repeat it ten times in this list. When something does not work in a complex app it is very hard to pinpoint the exact location of the failure. So having some tests gives you a very easy way to check if the problem is in the third-party library or somewhere else in your Mendix logic. Another good reason to have tests is to reduce the risks associated with making changes to your code or upgrading the library to a new version. You could theoretically do this in Mendix but that is much more complicated, resource and time intensive and harder to integrate in your build process compared to gradle or maven.
- Separate version control.
This is a minor point, but I really prefer keeping the dependencies in separate repositories. Plus you can use a different version control (git) system since you are not limited by Mendix (svn). And git already has good templates for both gradle and maven ignore lists.
To make the above best practice more grounded lets go over the steps for adding a concrete third-party library. How about a markdown parser https://github.com/vsch/flexmark-java? The one module in the Mendix app store about markdown conversion is now 7 years old and uses a deprecated library that is no longer maintained so this would be a nice upgrade.
The goal is to use this library in a Mendix project to convert some markdown text to HTML.
The end result should be something like this: https://markdownconverter-sandbox.mxapps.io
I will be using Gradle for this guide. Maven can do exactly the same.
Gradle v5.5: can be installed by following the official tutorial https://gradle.org/install/. Newer or older versions should also work but this is the one used in this tutorial.
It is a command line tool that takes care of dependency management, shadowing and building.
Step 1: Initialize the project