tableau / rest-api-samples

Samples for the Tableau REST API
MIT License
378 stars 268 forks source link

jaxbMarshaller.marshal(requestPayload, writer) throwing NullPointerException #58

Closed LaurenWallace closed 2 years ago

LaurenWallace commented 3 years ago

I have backend code in my application that needs the retrieved tableau view image passed to it like in the example below: `String tableauReportBase64Encoded = getStaticImage(tableauReportService.getTableauStaticReport(tableauConstants.getReportImagePath())); map.put("image1", tableauReportBase64Encoded);

private String getStaticImage(byte[] imageBytes) { String base64Encoded = null;

    if(imageBytes == null) {
        return null;
    }

    byte[] encodeBase64 = Base64.encodeBase64(imageBytes);

    try {
        base64Encoded = new String(encodeBase64, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return base64Encoded;
}`

I decided to try this way: `public byte[] getTableauStaticReport(String reportUrl) { TableauCredentialsType tableauCredentials = invokeSignIn(Constants.EMPTY_STRING);

    HttpGet getTableauReportImage = new HttpGet(reportUrl);
    getTableauReportImage.addHeader(TableauConstants.TABLEAU_AUTH_HEADER, tableauCredentials.getToken());
    byte[] tableauReportImageBytes = null;

    try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
        CloseableHttpResponse response = httpClient.execute(getTableauReportImage);
        InputStream imageInput = response.getEntity().getContent();
        tableauReportImageBytes = new byte[imageInput.available()];
        imageInput.read(tableauReportImageBytes);
    } catch (IOException e) {
        e.printStackTrace();
    }

    invokeSignOut(tableauCredentials);
    return tableauReportImageBytes;
}`

But I'm getting a NullPointerException on the jaxbMarshaller.marshal(requestPayload, writer) line of the below code that is used to sign in/make post requests to Tableau: `private TsResponse post(String url, String authToken, TsRequest requestPayload) { // 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 {
            jaxbMarshaller.marshal(requestPayload, writer);
        } catch (JAXBException ex) {
            logger.error("There was a problem marshalling the payload");
        }
    }

    // Converts the XML into a string
    String payload = writer.toString();
    logger.debug("Input payload: \n" + payload);

    HttpPost post = new HttpPost(url);
    List<NameValuePair> urlParameters = new ArrayList<>();
    urlParameters.add(new BasicNameValuePair(TableauConstants.TABLEAU_AUTH_HEADER, authToken));
    String responseXML = "";
    StringEntity payloadEntity = new StringEntity(payload, ContentType.TEXT_XML);

    try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
        CloseableHttpResponse response = httpClient.execute(post);

        // Parses the response from the server into an XML string
        HttpEntity responseEntity = response.getEntity();
        responseXML = responseEntity.toString();

        logger.debug("Response: \n" + responseXML);
    } catch (UnsupportedEncodingException encodingException) {
        encodingException.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    // Returns the unmarshalled XML response
    return unmarshalledResponse(responseXML);
}`

I checked the requestPayload, the name and password are set properly while site, token & user are null, and the writer object has the buf & lock set but the writeBuffer is null. I have not used jaxbMarshaller/StringWriter before but it seems like the marshaller needs the writer to be writing it to a StringBuilder or other object; or is it failing via NullPointerException for another reason?

I do have another question as well: I've tried all of the tableau api get view image calls in Postman and they all work except one that is giving me a 400074 error code. I checked the Tableau site and a 400074 error is a generic query error. Would you know how to troubleshoot that and should I create a separate question/issue for that/the question below?

It seems like that view requires a tableau user to connect to the data source before being able to see the view and that is probably causing the 400074 error. Is there a way to provide those credentials in the view image request?