Java API Tutorial

6 minutes to read Download PDF Edit

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, so not the entire code generated by the Modeler itself. It is advised to recreate the cases yourself and then try to execute the actions.

If 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.

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 passing parameters and obtaining 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 which we will place in the section BEGIN EXTRA CODE and END EXTRA CODE. The method will execute a microflow. This microflow 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.

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 1: In this line the method is defined. Obviously we’ll need the input String, but we’ll also need a context in which this microflow is executed.

Line 3: To pass parameters to a microflow, a Map is used. We’re using a HashMap 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.

Line 4: An entry is put in the HashMap containing the name of the parameter (“inputString”) and the value of the String.

Line 5: The Core method execute is called. This executes the microflow. It has the following parameters:

  • The context
  • The module name and microflow name
  • 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.

Line 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

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

Line 1: We obtain the value of the formatted String from our helper method.

Line 2: As you can see we have a testObject here. This is an entity of the MyFirstModule module and it’s called TestObject. This object was passed to the Java action and is available as a field in this entire Java action class. It is used to store the formatted String in, by calling a Set method on one of its String attributes.

Line 3: The Core method commit is called here. This will commit an object to tbe database. The context is passed, as well as the IMendixObject of the object we’re saving. This IMendixObject can be obtained from the proxy we’ve used.

Copying FileDocuments

A FileDocument is a System module entity which 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 which has a relation with an entity Attachment. The Attachment entity inherits from FileDocument. One GenericObject can have multiple Attachments. We’d like to copy Attachments from 1 GenericObject to another, so they can be independently modified later.

In the Java action we pass 2 GenericObjects as parameters, a sourceObject and destinationObject. We are going to copy all 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 an extra method getAttachments which returns a list of IMendixObjects. This code is put between the BEGIN EXTRA CODE and END EXTRA CODE in the Java action.

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();
	return Core.retrieveXPathQueryEscaped(context, "//%s[%s='%s']", attachmentEntityName, relationName, currentObjectID);
}

Line 1: Here the help method is defined. Its parameters are the GenericObject proxy object and the context we are performing the query in.

Line 3: The name of the Attachment entity is defined in a String, by copying the entityName from the Attachment proxy class.

Line 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.

Line 5: The ID of the currentObject is retrieved from the GenericObject proxy object method getGUID();

Line 6: The Core method retrieveXPathQueryEscaped is executed and its result (a list of IMendixObjects) is immediately returned. The parameters of this method are the context we wish to execute this query in and the actual query. By using the ‘escaped’ version of this method, xml characters in the parameters are being escaped. It also allows for easily readable code. The actual query “//%s[%s=‘%s’]” is being passed as a parameter and after that a number of Strings are passed which will take the place of the %s tokens.

The same query could have been executed using Core.retrieveXPathQuery() though. With that method you can enter additional parameters such as a sorting mechanism and a max number of objects returned. View the JavaDoc for more information.

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

The code between BEGIN USER CODE and END USER CODE:

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 1: Declaring an Attachment variable named newAttachment.

Line 2: Declaring an InputStream variable named inputStream.

Line 3: Starting to loop through a list of IMendixObjects returned by our helper method.

Line 5: Here we use the Core method getFileDocumentContent() passing our retrieved Attachment object to retrieve the InputStream of the actual file.

Line 6: A new Attachment is instanced.

Line 7: The relation to the destination object is set on our new Attachment.

Line 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 we’re performing this store in.
  • The IMendixObject of our Attachment proxy. This is retrieved by calling getMendixObject() on the Attachment proxy.
  • The file name of the FileDocument in String format. This filename is copied from the attachment we’re copying from by using the getValue() method passing the membername we wish to know the value of.
  • Last but not least, the InputStream containing the actual file.

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