Skip to main content

Threading in the Java SDK

Threads in a Java program help you achieve parallelism. By using multiple threads, you can make a Java program run faster and do multiple things simultaneously.

The Java SDK supports both single-threading and multi-threading irrespective of a single user or a multi user app.

Refer to the below code snippets that use multi-threading for a single-user and multi-user app.

Multi-threading in a Multi-user App

Multi-threading for multi-users is achieved using Initializer's static SwitchUser().


new Initializer.Builder()
    .user(user)
    .environment(environment)
    .token(token)
    .SDKConfig(config)
    .switchUser()

package threading.multiuser;

import com.zoho.api.authenticator.OAuthToken;

import com.zoho.api.authenticator.Token;

import com.zoho.api.authenticator.store.DBStore;

import com.zoho.api.authenticator.store.TokenStore;

import com.zoho.api.logger.Logger;

import com.zoho.crm.api.Initializer;

import com.zoho.crm.api.RequestProxy;

import com.zoho.crm.api.SDKConfig;

import com.zoho.crm.api.UserSignature;

import com.zoho.crm.api.dc.USDataCenter;

import com.zoho.crm.api.dc.DataCenter.Environment;

import com.zoho.crm.api.exception.SDKException;

import com.zoho.crm.api.record.RecordOperations;

import com.zoho.crm.api.util.APIResponse;

public class MultiThread extends Thread
{
    Environment environment;
    
    UserSignature user;
    
    Token token;
    
    String moduleAPIName;
    
    RequestProxy userProxy;
    
    SDKConfig sdkConfig;
    
    public MultiThread(UserSignature user, Environment environment, Token token, String moduleAPIName, SDKConfig config, RequestProxy proxy)
    {
        this.environment= environment;
        
        this.user = user;
        
        this.token = token;
        
        this.moduleAPIName = moduleAPIName;
        
        this.sdkConfig = config;
        
        this.userProxy = proxy;
    }
    
    public void run() 
    { 
        try
        { 
            new Initializer.Builder()
            .user(user)
            .environment(environment)
            .token(token)
            .SDKConfig(sdkConfig)
            .requestProxy(userProxy)
            .switchUser();
            
            System.out.println(Initializer.getInitializer().getUser().getEmail());
            
            RecordOperations cro = new RecordOperations();
            
            @SuppressWarnings("rawtypes")
            APIResponse getResponse = cro.getRecords(this.moduleAPIName, null, null);
  
            System.out.println(getResponse.getObject());
            
        } 
        catch (Exception e) 
        { 
            e.printStackTrace();
        } 
    } 
    
    
    public static void main(String[] args) throws SDKException
    {
        
        Logger loggerInstance = new Logger.Builder()
        .level(Logger.Levels.ALL)
        .filePath("/Users/user_name/Documents/java-sdk-logs.log")
        .build();
        
        Environment environment = USDataCenter.PRODUCTION;
        
        UserSignature user1 = new UserSignature("user1@zoho.com");
        
        TokenStore tokenstore = new DBStore.Builder()
        .host("hostName")
        .databaseName("databaseName")
        .tableName("tableName")
        .userName("userName")
        .password("password")
        .portNumber("portNumber")
        .build();
        
        Token token1 = new OAuthToken.Builder()
        .clientID("clientId1")
        .clientSecret("clientSecret1")
        .refreshToken("refreshToken")
        .redirectURL("redirectURL")
        .build();
        
        String resourcePath = "/Users/user_name/Documents";
        
        SDKConfig user1Config = new SDKConfig.Builder()
        .autoRefreshFields(false)
        .pickListValidation(true)
        .build();
        
        new Initializer.Builder()
        .user(user1)
        .environment(environment)
        .token(token1)
        .store(tokenstore)
        .SDKConfig(user1Config)
        .resourcePath(resourcePath)
        .logger(loggerInstance)
        .initialize();
        
        MultiThread multiThread = new MultiThread(user1, environment, token1, "Students", user1Config, null);
        
        multiThread.start();
        
        Environment environment1 = USDataCenter.PRODUCTION;
        
        UserSignature user2 = new UserSignature("user2@zoho.com");
        
        Token token2 = new OAuthToken.Builder()
        .clientID("clientId1")
        .clientSecret("clientSecret1")
        .refreshToken("refreshToken")
        .redirectURL("redirectURL")
        .build();
        
        RequestProxy user2Proxy = new RequestProxy.Builder()
        .host("proxyHost")
        .port(80)
        .user("proxyUser")
        .password("password")
        .userDomain("userDomain")
        .build();
        
        SDKConfig user2Config = new SDKConfig.Builder()
        .autoRefreshFields(true)
        .pickListValidation(false)
        .build();
        
        multiThread = new MultiThread(user2, environment1, token2, "Leads", user2Config, user2Proxy);
        
        multiThread.start();    
    }
}

  • The program execution starts from main().

  • The details of "user1" are given in the variables user1, token1, environment1.

  • Similarly, the details of another user "user2" are given in the variables user2, token2, environment2.

  • For each user, an instance of MultiThread class is created.

  • When start() is called which in-turn invokes run(), the details of user1 are passed to the switchUser function through the MultiThread object. Therefore, this creates a thread for user1.

  • Similarly, When start() is invoked again, the details of user2 are passed to the switchUser function through the MultiThread object. Therefore, this creates a thread for user2.

Multi-threading in a Single user App


package threading.singleuser;
import com.zoho.api.authenticator.OAuthToken;

import com.zoho.api.authenticator.Token;

import com.zoho.api.authenticator.store.FileStore;

import com.zoho.api.authenticator.store.TokenStore;

import com.zoho.api.logger.Logger;

import com.zoho.api.logger.Logger.Levels;

import com.zoho.crm.api.Initializer;

import com.zoho.crm.api.SDKConfig;

import com.zoho.crm.api.UserSignature;

import com.zoho.crm.api.dc.USDataCenter;

import com.zoho.crm.api.dc.DataCenter.Environment;

import com.zoho.crm.api.record.RecordOperations;

import com.zoho.crm.api.util.APIResponse;

public class MultiThread extends Thread
{
    String moduleAPIName;

    public MultiThread(String moduleAPIName)
    {
        this.moduleAPIName = moduleAPIName;
    }

    public void run()
    {
        try
        {
            RecordOperations record = new RecordOperations();

            @SuppressWarnings("rawtypes")
            APIResponse getResponse = record.getRecords(this.moduleAPIName, null, null);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws SDKException
    {
        Logger logger = new Logger.Builder()
        .level(Levels.INFO)
        .filePath("/Users/user_name/Documents/java-sdk-logs.log")
        .build();

        Environment environment = USDataCenter.PRODUCTION;

        TokenStore tokenStore = new FileStore("/Users/user_name/Documents/java-sdk-tokens.txt");

        UserSignature user = new UserSignature("user1@zoho.com");

        Token token = new OAuthToken.Builder()
        .clientID("clientId1")
        .clientSecret("clientSecret1")
        .refreshToken("refreshToken")
        .redirectURL("redirectURL")
        .build();

        SDKConfig sdkConfig = new SDKConfig.Builder()
        .autoRefreshFields(false)
        .pickListValidation(true)
        .build();

        String resourcePath = "/Users/user_name/Documents/javasdk-application";

        new Initializer.Builder()
        .user(user)
        .environment(environment)
        .token(token)
        .store(tokenstore)
        .SDKConfig(sdkConfig)
        .resourcePath(resourcePath)
        .logger(logger)
        .initialize();

        MultiThread mtsu = new MultiThread("Deals");

        mtsu.start();

        mtsu = new MultiThread("Leads");

        mtsu.start();
    }
}

Multi-threading in a Single-user App

  • The program execution starts from Main() where the SDK is initialized with the details of user and an instance of MultiThread class is created .
  • When the Start() is called which in-turn invokes the run(), the moduleAPIName is switched through the method parameter. Therefore, this creates a thread for the particular method called with the MultiThread instance.
  • The MultiThread object is reinitialized with a different moduleAPIName.

SDK Sample Code


import com.zoho.api.authenticator.Token;

import com.zoho.api.authenticator.store.DBStore;

import com.zoho.api.authenticator.store.FileStore;

import com.zoho.api.authenticator.store.TokenStore;

import com.zoho.crm.api.exception.SDKException;

import java.time.OffsetDateTime;

import java.time.ZoneOffset;

import java.util.Arrays;

import java.util.List;

import java.util.Map;

import com.zoho.api.authenticator.OAuthToken;

import com.zoho.crm.api.HeaderMap;

import com.zoho.crm.api.Initializer;

import com.zoho.crm.api.ParameterMap;

import com.zoho.crm.api.SDKConfig;

import com.zoho.crm.api.UserSignature;

import com.zoho.crm.api.dc.DataCenter.Environment;

import com.zoho.crm.api.dc.USDataCenter;

import com.zoho.api.logger.Logger;

import com.zoho.api.logger.Logger.Levels;

import com.zoho.crm.api.record.RecordOperations;

import com.zoho.crm.api.record.ResponseHandler;

import com.zoho.crm.api.record.ResponseWrapper;

import com.zoho.crm.api.tags.Tag;

import com.zoho.crm.api.record.RecordOperations.GetRecordsHeader;

import com.zoho.crm.api.record.RecordOperations.GetRecordsParam;

import com.zoho.crm.api.util.APIResponse;

public class Record
{

    public static void main(String[] args) throws SDKException
    {
        /*
         * Create an instance of Logger Class that takes two parameters
         * level -> Level of the log messages to be logged. Can be configured by typing Levels "." and choose any level from the list displayed.
         * filePath -> Absolute file path, where messages need to be logged.
         */
        Logger logger = new Logger.Builder()
        .level(Levels.INFO)
        .filePath("/Users/user_name/Documents/java-sdk-logs.log")
        .build();

        //Create an UserSignature instance that takes user Email as parameter
        UserSignature user = new UserSignature("abc@zoho.com");

        /*
        * Configure the environment
        * which is of the pattern Domain.Environment
        * Available Domains: USDataCenter, EUDataCenter, INDataCenter, CNDataCenter, AUDataCenter
        * Available Environments: PRODUCTION, DEVELOPER, SANDBOX
        */
        Environment environment = USDataCenter.PRODUCTION;

        /*
         * Create a Token instance
         * clientID -> OAuth client id.
         * clientSecret -> OAuth client secret.
         * refreshToken -> refresh token.
         * redirectURL -> OAuth redirect URL.
         */
        Token token = new OAuthToken.Builder()
        .clientID("clientId1")
        .clientSecret("clientSecret1")
        .refreshToken("refreshToken")
        .redirectURL("redirectURL")
        .build();

        /*
         * Create an instance of TokenStore.
         * host -> DataBase host name. Default "jdbc:mysql://localhost"
         * databaseName -> DataBase name. Default "zohooauth"
         * userName -> DataBase user name. Default "root"
         * tableName -> DataBase table name. Default "oauthtoken"
         * password -> DataBase password. Default ""
         * portNumber -> DataBase port number. Default "3306"
         */
//      TokenStore tokenstore = new DBStore.Builder().build();
        
        TokenStore tokenstore = new DBStore.Builder()
        .host("hostName")
        .databaseName("databaseName")
        .tableName("tableName")
        .userName("userName")
        .password("password")
        .portNumber("portNumber")
        .build();
        
//      TokenStore tokenstore = new FileStore("absolute_file_path");
        
        /*
        * autoRefreshFields (default value is false)
        * true - all the modules' fields will be auto-refreshed in the background, every hour.
        * false - the fields will not be auto-refreshed in the background. The user can manually delete the file(s) or refresh the fields using methods from ModuleFieldsHandler
        *
        * pickListValidation (default value is true)
        * A boolean field that validates user input for a pick list field and allows or disallows the addition of a new value to the list.
        * true - the SDK validates the input. If the value does not exist in the pick list, the SDK throws an error.
        * false - the SDK does not validate the input and makes the API request with the user’s input to the pick list
        */
        SDKConfig config = new SDKConfig.Builder()
        .autoRefreshFields(true)
        .pickListValidation(false)
        .build();
        
        String resourcePath = "/Users/user_name/Documents/javasdk-application";

        /*
          * Set the following in InitializeBuilder
          * user -> UserSignature instance
          * environment -> Environment instance
          * token -> Token instance
          * store -> TokenStore instance
          * SDKConfig -> SDKConfig instance
          * resourcePath -> resourcePath - A String
          * logger -> Log instance (optional)
          * requestProxy -> RequestProxy instance (optional)
        */
        new Initializer.Builder()
        .user(user)
        .environment(environment)
        .token(token)
        .store(tokenstore)
        .SDKConfig(config)
        .resourcePath(resourcePath)
        .logger(logger)
        .initialize();

        String moduleAPIName = "Leads";

        RecordOperations recordOperations = new RecordOperations();

        ParameterMap paramInstance = new ParameterMap();

        paramInstance.add(GetRecordsParam.APPROVED, "both");

        HeaderMap headerInstance = new HeaderMap();

        OffsetDateTime enddatetime = OffsetDateTime.of(2020, 05, 20, 10, 00, 01, 00, ZoneOffset.of("+05:30"));

        headerInstance.add(GetRecordsHeader.IF_MODIFIED_SINCE, enddatetime);

        //Call getRecords method
        APIResponseresponse = recordOperations.getRecords(moduleAPIName, paramInstance, headerInstance);

        if(response != null)
        {
            //Get the status code from response
            System.out.println("Status Code: " + response.getStatusCode());

            if(Arrays.asList(204,304).contains(response.getStatusCode()))
            {
                System.out.println(response.getStatusCode() == 204? "No Content" : "Not Modified");
                return;
            }

            //Check if expected response is received
            if(response.isExpected())
            {
                //Get the object from response
                ResponseHandler responseHandler = response.getObject();

                if(responseHandler instanceof ResponseWrapper)
                {
                    //Get the received ResponseWrapper instance
                    ResponseWrapper responseWrapper = (ResponseWrapper) responseHandler;

                    //Get the obtained Record instances
                    List records = responseWrapper.getData();

                    for(com.zoho.crm.api.record.Record record : records)
                    {
                        //Get the ID of each Record
                        System.out.println("Record ID: " + record.getId());

                        //Get the createdBy User instance of each Record
                        com.zoho.crm.api.users.User createdBy = record.getCreatedBy();

                        //Check if createdBy is not null
                        if(createdBy != null)
                        {
                            //Get the ID of the createdBy User
                            System.out.println("Record Created By User-ID: " + createdBy.getId());

                            //Get the name of the createdBy User
                            System.out.println("Record Created By User-Name: " + createdBy.getName());

                            //Get the Email of the createdBy User
                            System.out.println("Record Created By User-Email: " + createdBy.getEmail());
                        }

                        //Get the CreatedTime of each Record
                        System.out.println("Record CreatedTime: " + record.getCreatedTime());

                        //Get the modifiedBy User instance of each Record
                        com.zoho.crm.api.users.User modifiedBy = record.getModifiedBy();

                        //Check if modifiedBy is not null
                        if(modifiedBy != null)
                        {
                            //Get the ID of the modifiedBy User
                            System.out.println("Record Modified By User-ID: " + modifiedBy.getId());

                            //Get the name of the modifiedBy User
                            System.out.println("Record Modified By User-Name: " + modifiedBy.getName());

                            //Get the Email of the modifiedBy User
                            System.out.println("Record Modified By User-Email: " + modifiedBy.getEmail());
                        }

                        //Get the ModifiedTime of each Record
                        System.out.println("Record ModifiedTime: " + record.getModifiedTime());

                        //Get the list of Tag instance each Record
                        List tags = record.getTag();

                        //Check if tags is not null
                        if(tags != null)
                        {
                            for(Tag tag : tags)
                            {
                                //Get the Name of each Tag
                                System.out.println("Record Tag Name: " + tag.getName());

                                //Get the Id of each Tag
                                System.out.println("Record Tag ID: " + tag.getId());
                            }
                        }

                        //To get particular field value
                        System.out.println("Record Field Value: " + record.getKeyValue("Last_Name"));// FieldApiName

                        System.out.println("Record KeyValues: " );

                        //Get the KeyValue map
                        for(Map.Entry entry : record.getKeyValues().entrySet())
                        {
                            String keyName = entry.getKey();

                            Object value = entry.getValue();

                            if(value != null)
                            {
                                System.out.println("Field APIName : " + keyName + "\tValue : " + value.toString());
                            }
                        }
                    }
                }
            }
        }
    }
}
,>