Like what you see? Have a play with our trial version.

Error rendering macro 'rw-search'

null

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The following extract from a YFExport.xml file shows in red where tokens could be replaced by an automated process for generating a datasource for use with client source substitution.

...

<source>

   <id>132641</id>

   <sourceName>PostgreSQL Connection for[TENANT_NAME]</

...

sourceName>

   <sourceDescription>PostgreSQL Connection for [TENANT_NAME]</

...

sourceDescription>

   <databasePath>public</databasePath>

   <userName>[USERNAME]</

...

userName>

   <password>[ENCRYPTED_PASSWORD]</

...

password>

   <connectionTypeCode>GENERICUSER</connectionTypeCode>

   <connectionMethodCode>JDBC</connectionMethodCode>

   <connectionDriver>org.postgresql.Driver</connectionDriver>

   <databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]

...

></databaseURL>

   <databaseTypeCode>POSTGRESQL</databaseTypeCode>

   <minConnections>1</minConnections>

   <maxConnections>5</maxConnections>

   <connectionRefreshTime>180</connectionRefreshTime>

   <connectionTimeOut>180</connectionTimeOut>

   <accessCode>UNSECURE</accessCode>

   <maxRowCount>10000</maxRowCount>

   <maxAnalysisRowCount>0</maxAnalysisRowCount>

   <broadcastPermitted>true</broadcastPermitted>

   <subscribePermitted>true</subscribePermitted>

   <dataProfileEnabled>true</dataProfileEnabled>

   <localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode>

   <secondaryMinConnections>0</secondaryMinConnections>

   <secondaryMaxConnections>0</secondaryMaxConnections>

   <secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime>

   <secondaryConnectionTimeOut>0</secondaryConnectionTimeOut>

   <lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime>

   <sourceUUID>7d7543c0-e9c7-4a80-ab14-

...

73181e4d0694</sourceUUID>

   <filterList/>

   <sourceParameterList>

     <sourceParameter>

       <id>0</id>

       <parameterTypeCode>TEXT</parameterTypeCode>

       <parameterKey>DATABASE</parameterKey>

       <parameterIndex>0</parameterIndex>

       <parameterValue>[DATABASE_NAME]</

...

parameterValue>

       <documentId>0</documentId>

       <userVisible>true</userVisible>

     </sourceParameter>

     <sourceParameter>

       <id>0</id>

       <parameterTypeCode>TEXT</parameterTypeCode>

       <parameterKey>HOSTNAME</parameterKey>

       <parameterIndex>0</parameterIndex>

       <parameterValue>[SERVER_ADDRESS]</

...

parameterValue>

       <documentId>0</documentId>

       <userVisible>true</userVisible>

     </sourceParameter>

Once an export file has been automatically injected with tokens, it can be uploaded via the REST API using the the POST /api/rpc/import-export/import-content end-point, Import Content.

...

This takes a datasource model of this format:

Code Block
{

   "sourceName": "Client Database",

   "sourceDescription": "",

   "sourceType": "POSTGRESQL",

   "connectionType": "JDBC",

   "connectionTypeCode": "GENERICUSER",

   "connectionDriver": "org.postgresql.Driver",

   "connectionString": "jdbc:postgresql://192.168.1.100:5432/testdata",

   "connectionTimeout": 180,

   "userName": "postgres",

   "minimumConnections": 1,

   "maximumConnections": 5,

   "refreshTime": 180,

   "timezone": "AUSTRALIA/SYDNEY",

   "accessLevelCode": "UNSECURE",

   "maxRows": 10000,

   "maxAnalysisRows": 0,

   "inheritChildSourceFilters": false,

   "sourceLogIndicator": false,

   "sourceOptions": [

		{

		"optionKey": "ISOLATIONLEVEL",

		"optionValue": "1.0",

		"valueDataType": "1"

		},

		{

		"optionKey": "USESCHEMA",

		"optionValue": "true",

		"valueDataType": "6"

		},

		{

		"optionKey": "HOSTNAME",

		"optionValue": "192.168.1.100",

		"valueDataType": "2"

		},

		{

		"optionKey": "PORT",

		"optionValue": "5432",

		"valueDataType": "1"

		},

		{

		"optionKey": "DATABASE",

		"optionValue": "testdata",

		"valueDataType": "2"

		},

		{

		"optionKey": "YF_DRIVER_SELECTION",

		"optionValue": "org.postgresql.Driver",

		"valueDataType": "2"

		}

    ]

}

The main body of the model is similar to the model returned by the GET /api/data-sources end-point. If creating a new source similar to the Primary Organization datasource, the data returned by GET /api/data-sources can be used as a template.

...

The following examples illustrate how to create a new datasource via the POST /api/data-sources end-point:.

Code Block
languagejava
titleJava
collapsetrue
package rest.code.examples;
import java.io.IOException;
import java.util.Random;
import org.apache.hc.client5.http.fluent.Content;
import org.apache.hc.client5.http.fluent.Request;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* Create a datasource using the Yellowfin REST API
*/
public class CreateADataSource {
   public static void main(String[] args) throws Exception {
     
	    	String host = ""http://localhost:8080/yellowfinHead"";
	    	String restUsername = ""admin@yellowfin.com.au"";
	    	String restPassword = ""test"";
	    	
	    	String createDataSourcePayload = ""{\n""
	    			+ ""   \""sourceName\"": \""PostgreSQL Database Created Via Import\"",\n""
	    			+ ""   \""sourceDescription\"": \""\"",\n""
	    			+ ""   \""sourceType\"": \""POSTGRESQL\"",\n""
	    			+ ""   \""connectionType\"": \""JDBC\"",\n""
	    			+ ""   \""connectionTypeCode\"": \""GENERICUSER\"",\n""
	    			+ ""   \""connectionDriver\"": \""org.postgresql.Driver\"",\n""
	    			+ ""   \""connectionString\"": \""jdbc:postgresql://192.168.1.100:5432/testdata\"",\n""
	    			+ ""   \""connectionTimeout\"": 180,\n""
	    			+ ""   \""userName\"": \""postgres\"",\n""
	    			+ ""   \""minimumConnections\"": 1,\n""
	    			+ ""   \""maximumConnections\"": 5,\n""
	    			+ ""   \""refreshTime\"": 180,\n""
	    			+ ""   \""timezone\"": \""AUSTRALIA/SYDNEY\"",\n""
	    			+ ""   \""accessLevelCode\"": \""UNSECURE\"",\n""
	    			+ ""   \""maxRows\"": 10000,\n""
	    			+ ""   \""maxAnalysisRows\"": 0,\n""
	    			+ ""   \""inheritChildSourceFilters\"": false,\n""
	    			+ ""   \""sourceLogIndicator\"": false,\n""
	    			+ ""   \""sourceOptions\"": [\n""
	    			+ ""{\n""
	    			+ ""\""optionKey\"": \""ISOLATIONLEVEL\"",\n""
	    			+ ""\""optionValue\"": \""1.0\"",\n""
	    			+ ""\""valueDataType\"": \""1\""\n""
	    			+ ""},\n""
	    			+ ""{\n""
	    			+ ""\""optionKey\"": \""USESCHEMA\"",\n""
	    			+ ""\""optionValue\"": \""true\"",\n""
	    			+ ""\""valueDataType\"": \""6\""\n""
	    			+ ""},\n""
	    			+ ""{\n""
	    			+ ""\""optionKey\"": \""HOSTNAME\"",\n""
	    			+ ""\""optionValue\"": \""192.168.1.100\"",\n""
	    			+ ""\""valueDataType\"": \""2\""\n""
	    			+ ""},\n""
	    			+ ""{\n""
	    			+ ""\""optionKey\"": \""PORT\"",\n""
	    			+ ""\""optionValue\"": \""5432\"",\n""
	    			+ ""\""valueDataType\"": \""1\""\n""
	    			+ ""},\n""
	    			+ ""{\n""
	    			+ ""\""optionKey\"": \""DATABASE\"",\n""
	    			+ ""\""optionValue\"": \""testdata\"",\n""
	    			+ ""\""valueDataType\"": \""2\""\n""
	    			+ ""},\n""
	    			+ ""{\n""
	    			+ ""\""optionKey\"": \""YF_DRIVER_SELECTION\"",\n""
	    			+ ""\""optionValue\"": \""org.postgresql.Driver\"",\n""
	    			+ ""\""valueDataType\"": \""2\""\n""
	    			+ ""}\n""
	    			+ ""    ]\n""
	    			+ ""}""
	    			;
	    							  
	    			
	    	
	    	
	    	String token = generateToken(host, restUsername, restPassword);
	    	
	    	System.out.println(""Payload: "" + createDataSourcePayload);
	    	
	    	Content c = Request.post(host + ""/api/data-sources"")
	  	    		.addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong() + "", token="" + token)
	  	    		.addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
	  	    		.addHeader(""Content-Type"", ""application/json"")
	  	    		.bodyString(createDataSourcePayload, null)
	  	        .execute().returnContent();
	  	    	
	    System.out.print(c.asString());
	 
   }
  
   public static String generateToken(String host, String username, String password) throws IOException {
   	
   	  	Content c = Request.post(host + ""/api/refresh-tokens"")
 	    		.addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong())
 	    		.addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
 	    		.addHeader(""Content-Type"", ""application/json"")
 	    		.bodyString(""{ \""userName\"": \""""+ username + ""\"",\""password\"": \""""+ password + ""\""}"", null)
 	        .execute().returnContent();
 	    	
 	    JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject();
 	    JsonElement accessToken = jsonObject.getAsJsonObject(""_embedded"").getAsJsonObject(""accessToken"").get(""securityToken"");
 	   
 	    if (accessToken!=null) {
 	    		System.out.println(""Access Token: "" + accessToken);
 	    } else {
 	    		System.out.println(""Token not retrieved successfully"");
 	    		System.exit(-1);
 	    }
 	    return accessToken.getAsString();
   	
   }
  
}

...

A list of datasources can be retrieved with the GET /api/data-sources end-point, Get All Data Sources. This will return a datasource model of the following form:

Code Block
{

            "sourceId": 132780,

            "sourceName": "PostgreSQL Connection for NEWCLIENT",

            "sourceDescription": "PostgreSQL Connection for NEWCLIENT",

            "sourceType": "POSTGRESQL",

            "connectionType": "JDBC",

            "connectionTypeCode": "GENERICUSER",

            "connectionDriver": "org.postgresql.Driver",

            "connectionPath": "public",

            "connectionString": "jdbc:postgresql://localhost:5432/testdata",

            "connectionTimeout": 180,

            "userName": "postgres",

            "minimumConnections": 1,

            "maximumConnections": 5,

            "refreshTime": 180,

            "timezone": "AUSTRALIA/LORD_HOWE",

            "accessLevelCode": "UNSECURE",

            "maxRows": 10000,

            "maxAnalysisRows": 0,

            "inheritChildSourceFilters": false,

            "sourceLogIndicator": false

}

This service can be used to find the internal integer identifier for the datasource (sourceId) for a given data source name.

The following code examples illustrate how to retrieve a list of data sources from the system:.

Code Block
languagejava
titleJava
collapsetrue
package rest.code.examples;
import java.io.IOException;
import java.util.Random;
import org.apache.hc.client5.http.fluent.Content;
import org.apache.hc.client5.http.fluent.Request;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
 * List DataSources using the Yellowfin REST API
 */
public class ListDataSources {
    public static void main(String[] args) throws Exception {

        System.out.print(""List Datasources"");


        String host = ""http://localhost:8080/Yellowfin"";
        String restUsername = ""admin@yellowfin.com.au"";
        String restPassword = ""test"";

        String token = generateToken(host, restUsername, restPassword);

        Content c = Request.get(host + ""/api/data-sources"")
                .addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong() + "", token="" + token)
                .addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
                .addHeader(""Content-Type"", ""application/json"")
                .execute().returnContent();

        System.out.print(c.asString());

    }


    /*
     *  This function generates an access token for a user that will grant them access to
     *  call REST API endpoints.
     */

    public static String generateToken(String host, String username, String password) throws IOException {

        Content c = Request.post(host + ""/api/refresh-tokens"")
                .addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong())
                .addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
                .addHeader(""Content-Type"", ""application/json"")
                .bodyString(""{ \""userName\"": \""""+ username + ""\"",\""password\"": \""""+ password + ""\""}"", null)
                .execute().returnContent();

        JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject();
        JsonElement accessToken = jsonObject.getAsJsonObject(""_embedded"").getAsJsonObject(""accessToken"").get(""securityToken"");

        if (accessToken!=null) {
            System.out.println(""Access Token: "" + accessToken);
        } else {
            System.out.println(""Token not retrieved successfully"");
            System.exit(-1);
        }
        return accessToken.getAsString();

    }

}

...

The following examples illustrate how to link a Client Datasource (identified by its name) to a Primary Org Datasource (identified by its name):.

Code Block
languagejava
titleJava
collapsetrue
package rest.code.examples;
import java.io.IOException;
import java.util.Random;
import org.apache.hc.client5.http.fluent.Content;
import org.apache.hc.client5.http.fluent.Request;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
 * Attach a Client Datasource to Primary Org Source for Source Substitution using the Yellowfin REST API
 */
public class AttachClientDatasourceToPrimarySource {
    public static void main(String[] args) throws Exception {

        System.out.print(""Attach a Tenant Source to Primary Org Source for Source Substitution"");

        String host = ""http://localhost:8080/Yellowfin"";
        String restUsername = ""admin@yellowfin.com.au"";
        String restPassword = ""test"";

        String primarySourceName = ""PostgreSQL Connection at Primary Org"";
        String clientSourceName = ""PostgreSQL Connection for NEWCLIENT"";
        String clientOrgReference = ""NEWCLIENT"";

        String clientToken = generateToken(host, restUsername, restPassword, clientOrgReference);
        Integer clientOrgSourceId = findDataSourceForSourceNameAtClient(host, clientToken, clientSourceName);

        System.out.println(""Client Org Source Id: "" + clientOrgSourceId);

        String primaryToken = generateToken(host, restUsername, restPassword, null);
        Integer primaryOrgSourceId = findDataSourceForSourceNameAtClient(host, primaryToken, primarySourceName);

        System.out.println(""Primary Org Source Id: "" + clientOrgSourceId);

        Content c = Request.get(host + ""/api/data-sources/"" + primaryOrgSourceId + ""/client-data-sources/?clientSourceId="" + clientOrgSourceId)
                .addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong() + "", token="" + primaryToken)
                .addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
                .addHeader(""Content-Type"", ""application/json"")
                .execute().returnContent();

        System.out.print(c.asString());

    }

    /*
     *  This function finds a datasource for a given datasource name
     *  call REST API endpoints.
     */

    private static Integer findDataSourceForSourceNameAtClient(String host, String token, String sourceName) throws IOException {

        Content c = Request.get(host + ""/api/data-sources"")
                .addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong() + "", token="" + token)
                .addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
                .addHeader(""Content-Type"", ""application/json"")
                .execute().returnContent();

        JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject();
        JsonElement sourceList = jsonObject.get(""items"");
        JsonArray sources = sourceList.getAsJsonArray();

        for (int i=0; i < sources.size(); i++ ) {
            JsonObject source = sources.getAsJsonArray().get(i).getAsJsonObject();
            if (sourceName.equals(source.get(""sourceName"").getAsString())) return source.get(""sourceId"").getAsInt();
        }

        System.out.println(""Data Source could not be found for name:"" + sourceName);
        System.exit(-1);
        return null;

    }


    /*
     *  This function generates an access token for a user that will grant them access to
     *  call REST API endpoints.
     */

    public static String generateToken(String host, String username, String password, String tenantClientOrgRefId) throws IOException {

        String tokenBody = ""{ \""userName\"": \""""+ username + ""\"",\""password\"": \""""+ password + ""\"""";
        if (tenantClientOrgRefId!=null) {
            tokenBody = tokenBody + "",\""clientOrgRef\"": \""""+ tenantClientOrgRefId + ""\"""";
        }
        tokenBody = tokenBody + ""}"";

        Content c = Request.post(host + ""/api/refresh-tokens"")
                .addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong())
                .addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
                .addHeader(""Content-Type"", ""application/json"")
                .bodyString(tokenBody, null)
                .execute().returnContent();

        JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject();
        JsonElement accessToken = jsonObject.getAsJsonObject(""_embedded"").getAsJsonObject(""accessToken"").get(""securityToken"");

        if (accessToken!=null) {
            System.out.println(""Access Token: "" + accessToken);
        } else {
            System.out.println(""Token not retrieved successfully"");
            System.exit(-1);
        }
        return accessToken.getAsString();

    }

}

...