Advanced Techniques - Extending the Intrexx Connector for M-Files to all M-Files objects

The Connector for M-Files can only interact with objects with the type document. Usually, this is not enough for a project. In this article we will show you how you can extend the connector to work with every M-Files object. To do this, we need to enable scripting for the relevant Java classes and add a process; we'll be using Groovy here.

Preparing Intrexx to fully support all M-File objects

Copy the file scripting.cfg to the portal directory \internal\cfg\scriptingand then restart your portal service. The file can be downloaded from here. Configure the Connector for M-Files afterwards.

Groovy process

In this example, customers are managed in M-Files. Intrexx should be modified in such a way that the data is edited in Intrexx and no longer in M-Files. You need to build an application in Intrexx with an Intrexx data group for your customer data. Add a data field for each type of meta information in M-Files for your customers in Intrexx. Afterwards, create a new process and insert a Timer element. Then insert a Timer event handler. Add a Groovy action for synchronizing M-Files and Intrexx. You need this to initialize your customer data group correctly and to retrieve all future changes made in M-Files.



Add a three Data group actions that react to Insert, Edit and Delete actions in your customer data group, respectively and connect a Groovy action to each of them.

Login methods for M-Files with Groovy

Login based on the settings from the Intrexx data group

For this login method, a corresponding M-Files file field configuration is required in the Intrexx data group. The Groovy script to log in to M-Files is shown below.
import de.uplanet.lucy.server.mfiles.connector.*
import de.uplanet.scripting.groovy.util.Safely

def mfField = g_rtCache.fields["438574D09FB71551BED47EFD5FF03BA02A62656A"]// M-Files File Field GUID
def mfCfgGuid = mfField?.properties["mfiles.cfg.guid"]
g_log.info("mfCfgGuid: " + mfCfgGuid)
def mfVaultGuid = mfField?.properties["mfiles.vault.guid"]
def mfUserGuid = "903B5453FAE24B3618018562C316061F5C147346" // Intrexx User GUID with a static M-Files user
def mfService = MFilesService.getInstance()
def mfSession = mfService.login(mfCfgGuid, mfVaultGuid, mfUserGuid)

Login with username and password

In this case, you don't need to have an object with the type document. Here is the Groovy code:
import de.uplanet.lucy.server.mfiles.connector.*
import de.uplanet.scripting.groovy.util.Safely
def mfSession = mfService.login("mfileUser", "password", <VaultGuid>, <M-Files Service Configuration-GUID>)
You can find the M-Files Service Configuration GUID in the portal directory \internal\cfg\mfiles\*.xml.

The four supported HTTP methods

The following four HTTP methods are supported: GET, POST, PUT, DELETE. For a definition of the different String p_strService parameters, which will be used in the following definitions, please click here.

Definitions

GET statement

Structure:
httpReq.getAsString(IMFilesSession p_session, String p_strService,  Map<String, String> p_qsParam)
Example: Get all items from a value list.
def httpReq = new MFilesHttpRequest("http://mfiles/REST") // M-Files http request helper
/*
"http://mfiles/REST" - Enter the path to the M-Files REST service here.
*/
def response = httpReq.getAsString(mfSession, "/valuelists/2/items", [:])
def jsonObj = g_json.parse(response)  // Parse JSON string to JSON object
jsonObj["Items"].each { obj -> // Analyze objects in the value list
	g_log.info(obj)
	obj.each { prop -> // Analyze properties of the objects in the value list
	 g_log.info(prop)
	}
}

POST statement

Structure:
httpReq.postAsString(IMFilesSession p_session, String p_strService, Map<String, String> p_qsParam, String p_strJSON)
POST will only update the properties contained in the statement – all others will be unchanged. Example: Add the phone number property to a customer.
def httpReq = new MFilesHttpRequest("http://mfiles/REST") // M-Files http request helper
/*
"http://mfiles/REST" - Enter the path to the M-Files REST service here. */

def phone = g_record["91E9B6070ECF427AB1CB157BD2F30B6C98EFE9DC"].value /* datafield Telephone number <string> */
def json = """[{"PropertyDef":1085, "TypedValue":{"Value":"${phone}","DataType":1}}]"""
def response = httpReq.postAsString(mfSession, "/objects/${objType}/${objId}/latest/properties", [:], json.toString())if (httpReq.lastResponseCode <= 200 && httpReq.lastResponseCode >= 300)
	throw new Exception("Cannot update object in M-Files.", httpReq.lastResponseMsg)

PUT statement

Structure:
httpReq.putAsString(IMFilesSession p_session, String p_strService, String p_strJSON,  Map<String, String> p_qsParam)
PUT updates all of the properties contained in the PUT statement. This means that the already existing properties, which aren't contained in the PUT request, will be deleted. Example: Update the city, phone, addrLine1, addrLine2, country, website and zip code of an existing customer.
def httpReq = new MFilesHttpRequest("http://mfiles/REST") // M-Files http request helper
/*
"http://mfiles/REST" - Enter the path to the M-Files REST service here.
*/
def companyName = g_record["A912CE2C8A07B360D474FCBCA9776999FFEDDD40"].value /* datafield Customer name <string> */
def city = g_record["92B1D86B2AF96AD197934BD6BEFF503A8ED1E931"].value /* datafield City <string> */
def phone = g_record["91E9B6070ECF427AB1CB157BD2F30B6C98EFE9DC"].value /* datafield Telephone number <string> */
def addrLine1 = g_record["25816F534C9A08F435330D5347F283470728D5E2"].value /* datafield Address line1 <string> */
def addrLine2 = g_record["B37E65221D5CE1FA53EA52E8F4D4D27DC8DBBA98"].value /* datafield Address line2 <string> */
def country = g_record["13E26F368C3263EBD0056AEB2286EB9CE5E241FD"].value /* datafield Country <string> */
def website = g_record["56C987F67570C055431B11E57FCB58404C261977"].value /* datafield Website <string> */
def zip = g_record["33FBD51075EFF4D8285B99A9B2CEFAF211935A37"].value /* datafield ZIP/Postal code <string> */


def json = """{"PropertyValues": [
{"PropertyDef":1110, "TypedValue":{"Value":"${companyName}","DataType":1}},
{"PropertyDef":1085, "TypedValue":{"Value":"${phone}","DataType":1}},
{"TypedValue":{"Lookup":{"Item":78},"DataType":9}, "PropertyDef":100},
{"PropertyDef":1088, "TypedValue":{"Value":"${city}","DataType":1}},
{"PropertyDef":1073, "TypedValue":{"Value":"${addrLine1}","DataType":1}},
{"PropertyDef":1082, "TypedValue":{"Value":"${addrLine2}","DataType":1}},
{"PropertyDef":1090, "TypedValue":{"Lookup":{"Item":7},"DataType":10}},
{"PropertyDef":1086, "TypedValue":{"Value":"${website}","DataType":1}},
{"PropertyDef":1087, "TypedValue":{"Value":"${zip}","DataType":1}},
]}"""

def response = httpReq.putAsString(mfSession, "/objects/${objType}/${objId}/ latest/properties", json.toString(), [:])

if (httpReq.lastResponseCode <= 200 && httpReq.lastResponseCode >= 300)
	throw new Exception("Cannot update object in M-Files.", httpReq.lastResponseMsg)

def jsonResp = g_json.parse(response)
def objId = jsonResp.ObjVer.ID
def objVer = jsonResp.ObjVer.Version
def objType = jsonResp.ObjVer.Type

def conn = g_dbConnections.systemConnection
def stmt = null

try
{
	stmt = g_dbQuery.prepare(conn, "UPDATE DATAGROUP(<Intrexx DG-Guid>) SET L_OBJECTID=?, L_OBJECTVERSION=?, L_OBJECTTYPE=? WHERE STRID=?")

	stmt.setInt(1, objId)
	stmt.setInt(2, objVer)
	stmt.setInt(3, objType)
	stmt.setString(4, <STRID>)

	stmt.executeUpdate()
}
finally
{
	stmt = Safely.close(stmt)
}

DELETE statement

Structure:
httpReq.deleteAsString(IMFilesSession p_session, String p_strService, Map<String, String> p_qsParam, String p_strJson)
Example:
def httpReq = new MFilesHttpRequest("http://mfiles/REST") // M-Files http request helper
/*
"http://mfiles/REST" - Enter the path to the M-Files REST service here.
*/
def objType = g_record["2B7E7E29192A49070BFEEB35E099286C888BB27F"].value /* datafield Object-Type <integer> */
def objId = g_record["F2E54C2CC0D7FEE4BA80C931F4DF72DDC307A46F"].value /* datafield Object ID <integer> */
def objVer = g_record["08E12D364FA15DE1A4AB30E404A8521997565097"].value /* datafield Object Version <integer> */

def companyName = g_record["A912CE2C8A07B360D474FCBCA9776999FFEDDD40"].value /* datafield Customer name <string> */
def city = g_record["92B1D86B2AF96AD197934BD6BEFF503A8ED1E931"].value /* datafield City <string> */
def phone = g_record["91E9B6070ECF427AB1CB157BD2F30B6C98EFE9DC"].value /* datafield Telephone number <string> */

def json = """[{"PropertyDef":1085, "TypedValue":{"Value":"${phone}","DataType":1}}]"""
g_log.info("POST" + json)
def response = httpReq.deleteAsString(mfSession, "/objects/${objType}/${objId}/latest", ["allVersions":"true"], "{}")