2 Replies Latest reply on Sep 10, 2018 2:40 AM by Lucia Yang

    Publish Datasource in java gets 404 Resource not found

    Ted Teng

      I am using the TableauApiUtils.java attached in rest api java examples to publish datasource and append to an exsiting tde file in Tableau online. I am trying to upload several local extracts in a row to the same datasource. The first one will always succeed, response:


      <?xml version='1.0' encoding='UTF-8'?><tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.2.xsd"><datasource id="xxx" name="xxx" contentUrl="xxx" type="dataengine" createdAt="2016-09-26T22:46:30Z" updatedAt="2016-09-27T17:29:30Z"><project id="xxx" name="default" /><owner id="xxx" /><tags /></datasource></tsResponse>


      The following ones will always fail, response:


      <?xml version='1.0' encoding='UTF-8'?><tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.2.xsd"><error code="404015"><summary>Resource Not Found</summary><detail>File upload 'xxx' owned by user 'xxx' could not be found.</detail></error></tsResponse>


      I looked at the data source name in the request, they are exactly the same. Anyone knows what is wrong? Do I need to wait for a certain time for the server to propagate the change and upload again? Or should I refresh the datasource somehow before I upload again?


      Thanks a lot!


      Sample code I am using to publish datasource:


      private DataSourceType invokePublishDatasourceChunked(TableauCredentialsType credential, String siteId,
         String projectId, String datasourceName, File datasourceFile,
        boolean overwriteFlag, boolean appendFlag) {


         // Initiates a new file upload to get an upload session id
         FileUploadType fileUpload = invokeInitiateFileUpload(credential, siteId);

         // Builds the URL with the upload session id and workbook type
         UriBuilder builder = Operation.PUBLISH_DATASOURCE.getUriBuilder()

        .queryParam("uploadSessionId", fileUpload.getUploadSessionId())

        .queryParam("datasourceType", Files.getFileExtension(datasourceFile.getName()))

        .queryParam("overwrite", overwriteFlag ? "true" : "false")

        .queryParam("append", appendFlag ? "true" : "false");
         String url = builder.build(siteId, fileUpload.getUploadSessionId()).toString();

         // Creates a buffer to read 100KB at a time
         byte[] buffer = new byte[100000];

         // Reads the specified datasource and appends each chunk to the file upload
         try (FileInputStream inputStream = new FileInputStream(datasourceFile.getAbsolutePath())) {

         while (inputStream.read(buffer) != -1) {

        invokeAppendFileUpload(credential, siteId, fileUpload.getUploadSessionId(), buffer);

        } catch (IOException e) {

         throw new IllegalStateException("Failed to read the datasource file.");


         // Creates the payload to publish the workbook
         TsRequest payload = createPayloadToPublishDatasource(datasourceName, projectId);

         // Makes a multipart POST request with specified credential's
        // authenticity token and payload
         TsResponse response = postMultipart(url, credential.getToken(), payload, null);

         m_logger.info("datasource test1");

         // Verifies that the response has a workbook element
         if (response.getDatasource() != null) {

         m_logger.info("Publish datasource is successful!");

        return response.getDatasource();


         m_logger.info("datasource test2 " + response.getError() + " " + response.toString());

         // No datasource was published
         return null;



      private TsResponse postMultipart(String url, String authToken, TsRequest requestPayload, BodyPart filePart) {

         // Creates an instance of StringWriter to hold the XML for the request
         StringWriter writer = new StringWriter();

         // Marshals the TsRequest object into XML format if it is not null
         if (requestPayload != null) {

         try {

         s_jaxbMarshaller.marshal(requestPayload, writer);
         } catch (JAXBException ex) {

         m_logger.error("There was a problem marshalling the payload");



         // Converts the XML into a string
         String payload = writer.toString();

         m_logger.info("Input payload: \n" + payload);

         // Creates the XML request payload portion of the multipart request
         BodyPart payloadPart = new FormDataBodyPart(TABLEAU_PAYLOAD_NAME, payload);

         // Creates the multipart object and adds the file portion of the
        // multipart request to it
         MultiPart multipart = new MultiPart();

        if(filePart != null) {



         // Creates the HTTP client object and makes the HTTP request to the
        // specified URL
         Client client = Client.create();
         WebResource webResource = client.resource(url);

         // Makes a multipart POST request with the multipart payload and
        // authenticity token
         ClientResponse clientResponse = webResource.header(TABLEAU_AUTH_HEADER, authToken)

        .type(MultiPartMediaTypes.createMixed()).post(ClientResponse.class, multipart);

         // Parses the response from the server into an XML string
         String responseXML = clientResponse.getEntity(String.class);

         m_logger.info("Response: \n" + responseXML);

         // Returns the unmarshalled XML response
         return unmarshalResponse(responseXML);