Java in Custom Function

Custom functions help simplify complex, multi-step actions through program scripts that you can write and execute. Here are a few sample custom functions in Java that you can use in your organization.

Currently, Java custom functions are supported only in the US and IN data centers.
A maximum of 10 custom functions can be created in total for both Java and Node.js.

To know where custom functions are used in SrviceDesk Plus Cloud, click here.

Java code explained:

import com.zoho.cloud.function.Context;
import com.zoho.cloud.function.simple.*;
import com.zoho.cloud.connector.Connector;
import org.json.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.regex.*;
public class Class_1723115689756 implements ZCFunction<Void> {
public Void runner(Context context, Simple simple) throws Exception { // Do not modify this line
    return null;
}
}

The above is the sample function present when creating a new custom function.

import com.zoho.cloud.function.Context;
import com.zoho.cloud.function.simple.*;
import com.zoho.cloud.connector.Connector;
public class Class_1723115689756 implements ZCFunction<Void> {  
public Void runner(Context context, Simple simple) throws Exception { 

 

Runner method parameters:

Users can write any logic in Java only using the runner method. Other functions can be called inside the runner function. The runner method has 2 parameters:

 

Simple simple :

Custom functions can be used in many areas in ServiceDesk Plus Cloud. When the custom function is used in Business Rules or Triggers of the Request module, then the current request's JSON will be passed to the Custom function as input. You can fetch the data using the following syntax:

JSONObject requestObj = new
JSONObject(simple.getParameter("requestObj").toString()); 

If you are configuring a change trigger, then you will have data under 'changeObj' instead of 'requestObj'.

Similarly while executing a function, you will also get 'context' from ServiceDesk Plus Cloud, which will contain common details like App account id.

To get the value of 'context' use the following snippet.

new JSONObject(simple.getParameter("context").toString()); 

The following table contains the properties of each type of custom function.

Function Type

Input Parameters for Function

Expected output type from Function

Requests:

Trigger (or) Life cycle (or) Timer Actions

 

  • requestObj

    1. requestObj can be fetched by simple.getParameter("requestObj") inside 'runner' method.

    2. requestObj contains the request data of the currently processed trigger. The structure will be aligned with our v3 API structure.
      e.g.
      {
      “subject” : “New Issue”,
      “priority” : {
      “name” : “High”
      },
      ...}

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

      3. initialObj: Present only if the trigger is executed upon request edit and contains the initial request.

      4. modifiedFields: Present only if the trigger is executed upon request edit and contains the fields whose values are changed.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
},
“intialObj” : {
“subject” : “New Issue”,
“priority” : {
“name” : “Low”
},
“modifiedField : [“priority”]
}

Return null from the runner method to end the function.

Syntax:

return null; 

 

Requests:

Business Rule Actions

 

You need to return a requestObj which is of datatype Map.

Note: the data returned in this object will be saved in the request. The best practice would be to get the requestObj from input and update only the required fields, instead of constructing a new object.

Syntax:

return requestObj;

Requests:

Business Rule (or) Abort Timer Conditions (or) Workflow Actions

 

You need to return a Boolean. Note: the returned true/false data will be used in condition.

Syntax:

return true;

Requests:

Custom Menu Actions

 

You need to return a JSON object.

Note: the data returned in this object will be notified in popup.

Syntax:

return new JSONObject("{"success" : true/false, "message" : "<popup text>"}");

Problems:

Trigger (or) Life Cycle (or) Timer Actions

 

  • problemObj

    1. problemObj can be fetched by simple.getParameter("problemObj") inside 'runner' method.

    2. problemObj contains the problem data of the currently processed trigger. The structure will be aligned with our v3 API structure.
      e.g.
      {
      “title : “New Issue”,
      “priority” : {
      “name” : “High”
      },
      ...}

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
}

Return null from the runner method to end the function.

Syntax:

return null; 

Problems:

Abort Timer Conditions (or) Workflow Conditions (or) Workflow Actions

 

You need to return a Boolean. Note: the returned true/false data will be used in condition.

Syntax:

return true;

Problems:

Custom Menu Actions

 

You need to return a JSON object.

Note: the data returned in this object will be notified in popup.

Syntax:

return new JSONObject("{"success" : true/false, "message" : "<popup text>"}");

Changes:

Abort Timer Conditions (or) Workflow Conditions (or) Workflow Actions

 

  • changeObj

    1. changeObj can be fetched by simple.getParameter("changeObj") inside 'runner' method.

    2. changeObj contains the change data of the currently processed trigger. The structure will be aligned with our v3 API structure.
      e.g.
      {
      “title : “New Issue”,
      “priority” : {
      “name” : “High”
      },
      ...}

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
}

You need to return a Boolean. Note: the returned true/false data will be used in condition.

Syntax:

return true;

Changes:

Trigger (or) Timer Actions

 

Return null from the runner method to end the function.

Syntax:

return null; 

Changes:

Custom Menu Actions

 

You need to return a JSON object.

Note: the data returned in this object will be notified in popup.

Syntax:

return new JSONObject("{"success" : true/false, "message" : "<popup text>"}");

Projects:

Trigger Actions

 

  • projectObj

    1. projectObj can be fetched by simple.getParameter("projectObj") inside 'runner' method.

    2. projectObj contains the project data of the currently processed trigger. The structure will be aligned with our v3 API structure.
      e.g.
      {
      “title : “New Issue”,
      “priority” : {
      “name” : “High”
      },
      ...}

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
}

Return null from the runner method to end the function.

Syntax:

return null; 

Releases:

Trigger Actions

 

  • releaseObj

    1. releaseObj can be fetched by simple.getParameter("releaseObj") inside 'runner' method.

    2. releaseObj contains the release data of the currently processed trigger. The structure will be aligned with our v3 API structure.
      e.g.
      {
      “title : “New Issue”,
      “priority” : {
      “name” : “High”
      },
      ...}

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
}changeObj

  1. changeObj can be fetched by simple.getParameter("changeObj") inside 'runner' method.

  2. changeObj contains the change data of the currently processed trigger. The structure will be aligned with our v3 API structure.
    e.g.
    {
    “title : “New Issue”,
    “priority” : {
    “name” : “High”
    },
    ...}

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
}

Return null from the runner method to end the function.

Syntax:

return null; 

Releases:

Custom Menu Actions

 

You need to return a JSON object.

Note: the data returned in this object will be notified in popup.

Syntax:

return new JSONObject("{"success" : true/false, "message" : "<popup text>"}");

Releases:

Workflow (or) Timer Conditions

 

You need to return a Boolean. Note: the returned true/false data will be used in condition.

Syntax:

return true;

Solutions:

Trigger Actions

 

  • solutionObj

    1. solutionObj can be fetched by simple.getParameter("solutionObj") inside 'runner' method.

    2. solutionObj contains the solution data of the currently processed trigger. The structure will be aligned with our v3 API structure.
      e.g.
      {
      “title : “New Issue”,
      “priority” : {
      “name” : “High”
      },
      ...}

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
}

Return null from the runner method to end the function.

Syntax:

return null; 

Assets:

Workflow Conditions (or) Actions

 

  • assetObj

    1. assetObj can be fetched by simple.getParameter("assetObj") inside 'runner' method.

    2. assetObj contains the asset data of the currently processed trigger. The structure will be aligned with our v3 API structure.
      e.g.
      {
      “title : “New Issue”,
      “priority” : {
      “name” : “High”
      },
      ...}

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
}

You need to return a Boolean. Note: the returned true/false data will be used in condition.

Syntax:

return true;

Assets:

Trigger (or) Life Cycle Actions

 

Return null from the runner method to end the function.

Syntax:

return null; 

Assets:

Custom Menu Actions

 

You need to return a JSON object.

Note: the data returned in this object will be notified in popup.

Syntax:

return new JSONObject("{"success" : true/false, "message" : "<popup text>"}");

CMDB:

Trigger Actions

 

  • ciObj

    1. ciObj can be fetched by simple.getParameter("ciObj") inside 'runner' method.

    2. ciObj contains the CMDB data of the currently processed trigger. The structure will be aligned with our v3 API structure.
      e.g.
      {
      “title : “New Issue”,
      “priority” : {
      “name” : “High”
      },
      ...}

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
}

Return null from the runner method to end the function.

Syntax:

return null; 

CMDB:

Custom Menu Actions

 

You need to return a JSON object.

Note: the data returned in this object will be notified in popup.

Syntax:

return new JSONObject("{"success" : true/false, "message" : "<popup text>"}");

Purchases:

Trigger Actions

 

  • purchaseorderObj

    1. purchaseorderObj can be fetched by simple.getParameter("purchaseorderObj") inside 'runner' method.

    2. purchaseorderObj contains the purchase order data of the currently processed trigger. The structure will be aligned with our v3 API structure.
      e.g.
      {
      “title : “New Issue”,
      “priority” : {
      “name” : “High”
      },
      ...}

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
}

Return null from the runner method to end the function.

Syntax:

return null; 

Contracts:

Trigger Actions

 

  • contractObj

    1. contractObj can be fetched by simple.getParameter("contractObj") inside 'runner' method.

    2. contractObj contains the contract data of the currently processed trigger. The structure will be aligned with our v3 API structure.
      e.g.
      {
      “title : “New Issue”,
      “priority” : {
      “name” : “High”
      },
      ...}

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
}

Return null from the runner method to end the function.

Syntax:

return null; 

Configuration:

Trigger Actions

 

 

 

Scheduled Functions

 

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
}

You need to return a JSON object

Syntax:

return new JSONObject();

Callback Functions

 

  • <form data>

    1. <form data> can be fetched by simple.getParameter("<form data key>") inside 'runner' method.

    2. <form data> contains the data of the param passed from callback function.
      e.g.
      {
      “key" : “value”,
      ...}

  • context

    1. context can be fetched by simple.getParameter("context") inside 'runner' method.

    2. context contains the following details:

      1. instance: Portal in which the custom function is executed.

      2. userInfo: Logged in user details.

Sample Structure

{
“instance” : “itdesk”,
“userInfo” : {“userInfo” : {
“email_id” :
“sampleusername@manageengine.com”,
“type” : “requester/technician”,
Id>”
}

You need to return a JSON object

Syntax:

return new JSONObject();

 

Test execution:

In the development phase, you can print the data and see the output from any line using the Save & Execute Script option. You can do it by using the 'context' parameter which is passed to the runner method.

For example, to print "Hello world" you can use

context.log("Hello world"); 

Similarly, to print the contents of a request during test execution, you can use

context.log(simple.getParameter("requestObj").toString()); 

This is an alternative to System.out.print() in java.

Note: context.log() has no effect in actual execution. It is meant for test execution only.

 

Making API calls using Connections:

You can make API calls from custom functions using Connections. Click here to learn more.

After creating a Connection, copy the link name. The link name is a unique name generated while creating a connection. Click here to learn more.

Use the connector class below to get the connection object with the connection link name.

Connector connector = context.getConnection(connectionLinkName); 

Connector class extends Java's HttpURLConnection class. So once you have created a connection object using the above, you can make HTTP calls using the 'connector' object just like how you make the HTTP call with any HttpURLConnection's object.

Sample code:

The below sample code illustrates how to make an API call to ServiceDesk Plus v3 API. In this example, we will create a request with the subject "This test request is created from Custom function".

import com.zoho.cloud.function.Context;
import com.zoho.cloud.function.simple.*;
import com.zoho.cloud.connector.Connector;
import org.json.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.regex.*;
public class Class_1751608559930 implements ZCFunction<Void> {         // Do not modify this line
/**
* Makes an API call to the specified URL with the provided parameters, headers, and connection link name.
*
* @param context Pass the context object from runner method.
* @param url The URL to which the API call is made.
* @param method Method for HTTP call. Allowed values are GET, POST, PUT, DELETE.
* @param input_data The parameters to be sent with the API call, formatted as a JSONObject. Can be null if no parameters are needed.
* @param connectionLinkName The name of the connection link to use. Can be null if not needed.
* @return The response body.
* @throws Exception If an error occurs during the API call.
*/ 
 private static String makeSDPv3APIcall(Context context, String url, String method, JSONObject input_data, String connectionLinkName) throws Exception {
  Connector connector = context.getConnection(connectionLinkName);
  HttpURLConnection conn = connector.makeRequest(url);
  conn.setRequestMethod(method);
  conn.setDoInput(true);
  //Adding some headers that are necessary for ServiceDesk Plus v3 APIs.
  conn.setRequestProperty("Accept", "vnd.manageengine.v3+json");
  conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
  conn.setDoOutput(true);
  OutputStream os; 
  if(input_data != null){
   StringBuilder inputData = new StringBuilder();
   inputData.append("input_data=");
   String value = URLEncoder.encode(input_data.toString(), "UTF-8");
   inputData.append(value);
   os = conn.getOutputStream();
   os.write(inputData.toString().getBytes("UTF-8"));
  }
  else{
   os = conn.getOutputStream();
  }
  os.close();
  int responseCode = conn.getResponseCode(); // triggers the call
  BufferedReader br;
  if (responseCode < 300) {
   br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
  } else {
   br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
  }
  StringBuilder apiResponse = new StringBuilder();
  String outputLine;
  while ((outputLine = br.readLine()) != null) {
   apiResponse.append(outputLine);
  }
  return apiResponse.toString();
}
 public Void runner(Context context, Simple simple) throws Exception { // Do not modify this line
  String connection = "<YOUR_CONNECTION_LINK_NAME_HERE>";
  String method = "POST";
  String url = "https://sdpondemand.manageengine.com/api/v3/requests";
  JSONObject inputData = new JSONObject().put("request", new JSONObject().put("subject", "This test request is created from Custom function"));
  String resp = makeSDPv3APIcall(context, url, method, inputData, connection);
  context.log(resp);
  return null;
}
}

Sample Functions:

Java Code that returns Boolean:

public Boolean runner(Context context, Simple simple) throws Exception {
    try{
        JSONObject requestObj = new JSONObject(simple.getParameter("requestObj").toString());
        JSONObject priority = requestObj.getJSONObject("priority");
        context.log(priority.toString());
        if(priority != null && priority.getString("name").equals("Low")){
            return true;
        }
        return false;
    }catch(Exception e){
        context.log("Exception - " + e.toString());
          return false;
    }
}

Java Code that returns RequestObject JSONObject:

public JSONObject runner(Context context, Simple simple) throws Exception {
    JSONObject jsonObject = new JSONObject(simple.getParameter("requestObj").toString());  
    JSONObject priority = new JSONObject();
    priority.put("name","Medium");
    jsonObject.put("priority", priority);
context.log(jsonObject.toString());
    return jsonObject;
}