Use the Java API

Last modified: December 5, 2023

1 Introduction

This tutorial contains some examples of how to use the Java API provided by the Mendix Runtime. The tutorial assumes you have basic Java knowledge as well as basic Mendix modeling knowledge.

To avoid cluttering the tutorial, only the relevant code will be 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 will be 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’re working will determine if you have these rights and can perform that action.

This how-to teaches you how to do the following:

  • Execute microflows and commit objects
  • Copy FileDocuments

2 Executing Microflows and Committing Objects

There are cases in which you’d like to execute a microflow in a Java Action. This case will explain 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.

First, we will introduce a helper method that we will place in the section BEGIN EXTRA CODE and END EXTRA CODE. The method 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.

1
2
3
4
5
6
7
private static String formatString(String inputString, IContext context) throws CoreException
{
	Map<String,Object> parameters = new HashMap<String, Object>();
	parameters.put("inputString", inputString);
	String formattedString = (String) Core.execute(context, "MyFirstModule.FormatString", parameters);
	return formattedString;
}
Line Description
1 In this line, the method is defined. We’ll need the input string, and we’ll also need the context in which this microflow is executed.
3 To pass parameters to a microflow, a map is used. A HashMap is being used here. The map consists of a string key, which holds the name of the parameter in the microflow, and an object value, which holds the value of the parameter.
4 An entry is put in the HashMap containing the name of the parameter (inputString) and the value of the string.
5 The core method executed is called. This executes the microflow. It has the following parameters: the context, the module name and microflow name, and the parameter map. The method always returns an object which can be cast to the type that the microflow returns, in this case a string.
6 The microflow return value is returned by our helper method.

Once we have the value of the formatted string, we are going to store this in an object. This is the code between BEGIN USER CODE and END USER CODE.

1
2
3
String formattedString = formatString("this is an unformatted string", context);
testObject.setTestString(context, formattedString);
Core.commit(context, testObject.getMendixObject());

3 Copying FileDocuments

A FileDocument is a system module entity that holds the content of a file (for example, a text file or Excel sheet). For this case, we assume we 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. We’d like to copy the Attachments from one GenericObject to another so that they can be independently modified later.

In the Java Action, we pass two GenericObjects as parameters, a sourceObject, and a destinationObject. We are going to copy all the Attachments from the sourceObject to the destinationObject.

To be able to copy Attachments, we will 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 we 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 We 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 fill the variable currentid with the ID of the current object. We pass the context in which we 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, these are taken into account. View the JavaDoc for more information.

Now that we have a way to get all the Attachments from a certain GenericObject, we 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’re 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 have been copied to another.

4 Read More