Integrating Tableau to the Data Service
As Tableau needs to retrieve the data from the Platform application, some dedicated HTTP endpoints need to be enabled in the Platform.
To add Tableau endpoints in the Data Service, you need to add the dependency to a built-in library. To do so, edit the extensions/data-service-extension/build.gradle
Gradle configuration file and enrich the dependency block as in the following example:
dependencies { ... // Tableau implementation "com.decisionbrain.gene:data-tableau-base:${versions.decisionbrain.dbgene}" }
You also have to create a Java configuration that adds the Tableau HTTP controller to the Data Service. To do so, add a TableauConfiguration
class with the @EnableTableau
in the data-service-extension
as in the following code:
package com.example.caplan.data.configuration; import com.decisionbrain.gene.tableau.dataservice.EnableTableau; import org.springframework.context.annotation.Configuration; @Configuration @EnableTableau public class TableauConfiguration { }
Some configurations need to be added to help the Data Service to know how to reach Tableau Server
tableau-client: enabled: true host: <the-url-of-your-Tableau-server> credentials: username: tableauUser password: tableauPassword
When deploying using a Helm chart, add the following values to your environment values YAML file:
<your-application-chart-name>: dataService: env: GATEWAY_SERVER_URL: value: "https://www.my-platform-application.my-company.com" API_KEY_CLIENT_BASE_URL: value: "https://www.my-platform-application.my-company.com/api/scenario"
When Tableau retrieves the data from the Platform application, it asks for the data associated with the web data connector name. This data is retrieved from scenarios. The scenarios to be associated with a given web data connector are resolved by a component called TableauRefreshLifecycleHandler
in the Platform application. (As the name suggests, this component also provides hooks that are called and the start and end of the data refresh operations.)
The default implementation of this component associates scenarios with a web data connector, based on the users choice. If you need a different resolution algorithm, you will have to code your own logic as a Spring component in the data-service-extension
that implements the TableauRefreshLifecycleHandler
interface, and annotate it as @Primary
.
Here an example that retrieves all the available scenarios for the user that has created the Web Data Connector.
@Primary @Component public class CustomTableauRefreshLifecycleHandler implements TableauRefreshLifecycleHandler { private static final Logger LOGGER = LoggerFactory.getLogger(CustomTableauRefreshLifecycleHandler.class); private final ScenarioServiceClient scenarioServiceClient; @Autowired public CustomizedResolveScenarioHandler(ScenarioServiceClient scenarioServiceClient) { this.scenarioServiceClient = scenarioServiceClient; } @Override public void refreshStarted(@NonNull String connectorId) throws MultipleWorkbooksException { LOGGER.info("Start refresh for WDC {}", connectorId); } @Override public void refreshCompleted(@NonNull String connectorId) throws MultipleWorkbooksException { LOGGER.info("Completed refresh for WDC {}", connectorId); } @Override public void refreshFailed(@NonNull String connectorId, String errorMessage) throws MultipleWorkbooksException { LOGGER.error("Failed refresh for WDC {}: {}", connectorId, errorMessage); } @Override public List<String> resolveScenarioIds(String connectorId) { LOGGER.info("Resolving Scenarios for WDC: {}", connectorId); var allScenarios = Optional.ofNullable(scenarioServiceClient.getScenarios(null, null).getBody()) .map(scenarios -> scenarios.stream() .map(PathDTO::getUuid) .filter(Objects::nonNull) .toList() ).orElse(List.of()); // Add your custom logic here return allScenarios; } }