Using the Mendix Runtime Java API

Last modified: December 5, 2023

1 Introduction

This tutorial contains some examples of how to use the Mendix Runtime Java API. The tutorial assumes that you have some basic Java and Mendix modeling knowledge.

To avoid cluttering the tutorial, only the relevant code is shown, not the entire code generated by Studio Pro itself. Recreating the cases yourself and then trying to execute the actions is recommended.

When you look at these examples, often an IContext is used. This is the context in which something can be done. For example, it holds access rights to objects. If you do something with an object that requires access rights, the context in which you are working will determine whether you have these rights and can perform that action.

This tutorial teaches you how to do the following:

  • Execute microflows and commit objects
  • Copy FileDocuments

2 Executing Microflows and Committing Objects

Sometimes you want to execute a microflow in a Java Action. This section explains how to do this, including how to pass parameters and obtain the return value. Additionally, the result will be saved in an object and the object will be committed.

In this example, you will execute a microflow that is called FormatString and is part of the MyFirstModule module. It has an input parameter called inputString, which is a string. Its return value is also a string, which contains the formatted string.

You can invoke the microflow directly using its proxy:

1
myfirstmodule.proxies.microflows.Microflows.formatString(getContext(), "this is an unformatted string");

But you can make your code more readable by first importing the proxy before the class declaration, and then referring to the microflow directly.

1
2
3
4
5
6
import static myfirstmodule.proxies.microflows.Microflows.formatString;

public class 

String formattedString = formatString(getContext(), "this is an unformatted string");

Once you have the value of the formatted string, you can store this in an object and then commit the object.

The code below formats the string "this is an unformatted string" using the microflow MyFirstModule.FormatString, stores it in the TestString attribute of an object of entity testObject, and then commits the object. The code is placed between BEGIN USER CODE and END USER CODE of the Java action.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import static myfirstmodule.proxies.microflows.Microflows.formatString;

public class 

// BEGIN USER CODE
String formattedString = formatString(getContext(), "this is an unformatted string");
testObject.setTestString(context, formattedString);
Core.commit(context, testObject.getMendixObject());
// END USER CODE

3 Copying FileDocuments

A FileDocument is a system module entity that holds the content of a file (for example, a text file or an Excel sheet). For this case, you have an entity called GenericObject that has a relation with an Attachment entity. The Attachment entity inherits from FileDocument. One GenericObject can have multiple Attachments. You copy the Attachments from one GenericObject to another so that they can be independently modified later.

In the Java Action, you pass two GenericObjects as parameters, a sourceObject and a destinationObject. You will also copy all the Attachments from the sourceObject to the destinationObject.

To be able to copy Attachments, you first need to retrieve them. For this purpose, we introduce the extra method called getAttachments, which returns a list of IMendixObjects. This code is put between BEGIN EXTRA CODE and END EXTRA CODE in the Java action.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public static List<IMendixObject> getAttachments(GenericObject object, IContext context) throws CoreException
{
	String attachmentEntityName = Attachment.entityName;
	String relationName = Attachment.MemberNames.Attachment_GenericObject.toString();
	String currentObjectID = object.getGUID();
	String query = String.format("//%s[%s=$currentid]", attachmentEntityName, relationName);
	return Core.createXPathQuery(query)
		.setVariable("currentid", currentObjectID)
		.execute(context);
}
Line Description
1 The help method is defined here. Its parameters are the GenericObject proxy object and the context in which you are performing the query.
3 The name of the Attachment entity is defined in a String by copying the entityName from the Attachment proxy class.
4 The name of the relation between the Attachment entity and GenericObject entity is defined in a String by getting it from the MemberNames enumeration of the Attachment proxy class and calling toString() on it.
5 The ID of the currentObject is retrieved from the GenericObject proxy object method getGUID();.
6 You construct a query on the Attachment entity that is related to the object with currentid. The prefix $ denotes that this is a variable, which can later be safely inserted using the Core.createXPathQuery API.
7 The Core method createXPathQuery is used to create a query. This query fills the variable currentid with the ID of the current object. You pass the context in which you want the query to be executed. After this, its result (a list of IMendixObjects) is immediately returned.

Using the createXPathQuery API, you can also enter conditions, such as a sorting mechanism and a maximum number of objects returned. After executing the query, these are taken into account. View the JavaDoc for more information.

Now that you have a way to get all the Attachments from a certain GenericObject, you can start copying them.

This is the code between BEGIN USER CODE and END USER CODE:

1
2
3
4
5
6
7
8
9
Attachment newAttachment;
InputStream inputStream;
for (IMendixObject iMendixObject: getAttachments(sourceObject, context))
{
	inputStream = Core.getFileDocumentContent(iMendixObject);
	newAttachment = Attachment.create(context);
	newAttachment.setAttachment_GenericObject(destinationObject);
	Core.storeFileDocumentContent(context, newAttachment.getMendixObject(), (String) iMendixObject.getValue(system.proxies.Document.MemberNames.Name.toString()),  inputStream);
}
Line Description
1 Declaring an Attachment variable named newAttachment.
2 Declaring an InputStream variable named inputStream.
3 Starting to loop through a list of IMendixObjects returned by our helper method.
5 Here the Core method getFileDocumentContent() is used, passing the retrieved Attachment object to retrieve the InputStream of the actual file.
6 A new Attachment is instanced.
7 The relation to the destination object is set on our new Attachment.
8 The content of the retrieved InputStream is stored in our new Attachment using the Core method storeFileDocumentContent(). This method takes a number of parameters: the context in which you are performing this store; the IMendixObject of the Attachment proxy, which is retrieved by calling getMendixObject() on the Attachment proxy; the file name of the FileDocument in string format, which is copied from the attachment you are copying from by using the getValue() method passing the member name you wish to know the value of; and the InputStream containing the actual file.

After this, all Attachments belonging to one GenericObject are copied to another.

4 Read More