Getting the current language code in a Mendix app from JavaScript

When we’re working on a multi language application, we need to be aware of the user’s language ensure they receive content in their own language.

Mendix has great language support, and it also has great caching on the client side. These can cause problems together when you change the language of a user in your application, it may not always be reflected back to local cache.

There is a way around this, we can use the Mendix Client API to force a retrieve of the data from the application. We need to use an XPath request to ensure we bypass the cache.

let xPath = "//System.Language[System.User_Language=\"" + mx.session.getUserId() + "\"]";

We have the current user’s session ID, so we can retrieve the System.Language using this a constraint on the System.User_Language association.

Now we can just use an mx.data.get call to retrieve it.

mx.data.get({
    xpath: xPath,
    filter: {
        amount: 1
    }, 
    callback: function(obj) { 
        let lang = obj[0].jsonData.attributes.Code.value;
        console.log("Current language is " + lang);
    }
});

In this example, we are just echoing the language code back to the user on the console.

Logging from a Mendix Java action

How to add logging to a Mendix Java action.

It is a common requirement to be able to log data from an application. Mendix has a good logging system built in, but how do we access this from a custom Java action?

The Mendix development team have already thought of this, and have provided a method called getLogger in the Core.

To use the logger from a Java action, we first need to add a couple of imports.

import com.mendix.core.Core;
import com.mendix.logging.ILogNode;

Now we need to provide access to the logger. We can do this by providing a static variable which we’ll call LOG. We use the getLogger method we mentioned earlier, passing in the name of the log node name we want to use. In this case, we’ll use “RobTest” as the log node name.

// BEGIN EXTRA CODE
public static ILogNode LOG = Core.getLogger("RobTest");
// END EXTRA CODE

Now, this is in place, we can access LOG from elsewhere in our Java action.

Let’s say our action wants to log when it starts and also wants to list all the microflows available within the App. We can change the log levels, so the start notification is at “info” level, and the microflows are at “debug” level. We can do this using the following.

public java.lang.Boolean executeAction() throws Exception
{
    // BEGIN USER CODE
    LOG.info("Running executeAction()");

    for (String mf : Core.getMicroflowNames()) {
        LOG.debug("Microflow: " + mf);
    }
    return true;
    // END USER CODE
}

When we execute the Java action, we see the following on the Mendix console.

Debugging a Mendix widget

I had to debug a custom Mendix widget that was failing. All that was shown on screen in red was “Could not create widget BHCCDropZone.widget.BHCCDropZone”.

We’d recently upgraded to Mendix 7.18.1, so something looked like it happened during the upgrade.

The first step was to make sure the appropriate access rights to the entity the widget uses were right. In this case they were.

Next was to up the log levels from INFO to DEBUG in the Mendix Modeller to see if that gave me any clues. I could see the widget’s constructor and postCreate being run as I had logger.debug calls in those functions being run. However, one of my debug calls was not being reached, so I had narrowed down the location of problem.

After this I added JavaScript breakpoints in the failing method using Chrome’s developer tools. The widget is only loaded the first time the page is reached. When I reached this page I singled stepped through, and found an exception being thrown by the JavaScript but being caught by Mendix. My error was…

"TypeError: Converting circular structure to JSON
    at JSON.stringify ()
    at http://localhost:8080/mxclientsystem/mxui/mxui.js?636758982080189581:74:164930
    at Array.map ()
    at t.log (http://localhost:8080/mxclientsystem/mxui/mxui.js?636758982080189581:74:164840)
    at http://localhost:8080/mxclientsystem/mxui/mxui.js?636758982080189581:74:196250
    at http://localhost:8080/mxclientsystem/mxui/mxui.js?636758982080189581:74:166406
    at Array.forEach ()
    at t.log (http://localhost:8080/mxclientsystem/mxui/mxui.js?636758982080189581:74:166377)
    at t.debug (http://localhost:8080/mxclientsystem/mxui/mxui.js?636758982080189581:74:165718)
    at Object.postCreate (http://localhost:8080/widgets/BHCCDropZone/widget/BHCCDropZone.js?636758982080189581:80:11)"

I could now see I had a circular data structure.

Working backwards through the stack trace, I could see the problem was in my widget’s postCreate function, and it was a debug function causing the problem. This was the faulty code causing the widget to fail.

My postCreate function looked like this…

postCreate: function () {
  console.log("BHCCDropZone session", mx.session);
  logger.debug(this.id + ".postCreate");
  this.initBHCCDropZone();
  logger.debug("this", this);
},

The faulty line was this…

logger.debug("this", this);

Trying to send the contents of this to the debug logs was causing problems as it was a circular data structure. Removing this line of JavaScript fixed the problem, and the widget started to work again as expected.

I hope this helps others in future when debugging “Could not create widget” errors in Mendix.

Using a http proxy from a Mendix Java action

As part of some work I have been undertaking to integrate the UK Government Notifications service into Mendix, I needed to be able to make API calls from behind a firewall using a proxy in a Java action.

Due to the lower level Java actions in Mendix run at, proxy settings are not automatically applied, and must be added manually. I wanted to explain how to get the proxy settings from Mendix, and use them a Java action.

I’ve previously explained how to add proxy settings to Mendix, so I assume this step has been completed.

In a Java action, we need to get these from the HttpConfiguration singleton.

import com.mendix.http.HttpConfiguration;
import com.mendix.http.IHttpConfiguration;
import com.mendix.http.IProxyConfiguration;

IHttpConfiguration httpconf = com.mendix.http.HttpConfiguration.getInstance();
IProxyConfiguration proxyconf = httpconf.getProxyConfiguration().orElse(null);

We can now check if we have a proxy configuration set, if we don’t proxyconf will be null.

The username and password for the proxy can be retrieved using the getUser() and getPassword() methods.

String username = proxyconf.getUser().orElse(null);
String password = proxyconf.getPassword().orElse(null);

If they are present we can build a Java Authenticator object and set it as the default authenticator.

import java.net.Authenticator;
import java.net.PasswordAuthentication;

if (username != null && password != null) {
    Authenticator authenticator = new Authenticator() {
        public PasswordAuthentication getPasswordAuthentication() {
           return (new PasswordAuthentication(username, password.toCharArray()));
        }
    };

    Authenticator.setDefault(authenticator);
}

Next we need to create the Proxy object. We need to get the host and port of our proxy server from Mendix using the getHost() and getPort() methods.

import java.net.InetSocketAddress;
import java.net.Proxy;

InetSocketAddress proxyLocation = new InetSocketAddress(proxyconf.getHost(), proxyconf.getPort());
Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyLocation);

The proxy can be used for Java network actions.

An example of using this would be the UK Government Notifications client. It has a second optional paramater in it’s constructor for a Proxy.

client = new NotificationClient('APIKey', proxy);

Using a proxy server from the Mendix Modeller

There are times when building online services you find yourself behind a firewall and need to use a proxy. Sometimes these are transparent, but other times you need to add settings by hand.

In a Mendix app, an example may be when you need to consume a REST service from outside you home network.

To configure proxy settings in Mendix, you need to go to our Project’s “Settings”. Open “Configurations”, select your working configuration, and click “Edit”. Select the “Custom” tab and add the following “Names” and “Values”.

http.proxyHost The name your proxy
http.proxyPort The port your proxy is running off of.

If my proxy was running on proxy.robertprice.co.uk:8080, my settings would be

http.proxyHost proxy.robertprice.co.uk
http.proxyPort 8080

Sometimes the proxy will also need a username and password. You can set these using http.proxyUser and http.proxyPassword. For example

http.proxyUser RobertPrice
http.proxyPassword SecretPassword

You should now be able to access external services through the proxy from Mendix.

Example proxy settings for the Mendix Modeller

More information on using a proxy in Mendix is available at Using a proxy to call a REST service.

Extracting text in Mendix using RegexReplaceAll

It’s a fairly common requirement to be able to extract text from a larger string.

Using Mendix, the easiest way I’ve found to do this is using the RegexReplaceAll Java action from the Community Commons module.

We use a regular expression extract the text, then return this selected text in the action.

For example, take the following string returned from the Nexmo SMS module.

--------- part [ 1 ] ------------Status [ 9 ] ...SUBMISSION FAILED!Message-Id [ null ] ...Error-Text [ Quota Exceeded - rejected ] ...Message-Price [ 0.03330000 ] ...Remaining-Balance [ 0.03200000 ]

If we want to extract the Error-Text we can use the following regular expression.

^.*Error-Text \[ (.*?) \].*$

Here we’re saying look for the text between the square brackets after the string Error-Text. We use round brackets to say we want to remember this matched text. We can then use the regular expression match position to return the matched text – in this case $1.

If we run this over our string we get the following

Quota Exceeded - rejected

To use this in a Mendix microflow, assume we have our status message in a String $StatusMessage that we pass into the Java action. This is our Haystack.

Next, we use the regular expression as a String for our Needle regex.

Finally, we say we want $1 as a String to be our Replacement.

We return the String as $Details.

This is what the microflow and action should look like.

View Robert Price’s Mendix Profile.