Error Handling
Error handling is important to ensuring your applications inform an end user when something goes wrong and The DynamicPDF API is no exception.
DynamicPDF API provides error responses as a JSON message describing the error. All client libraries provide the following:
- An HTTP status.
- A JSON error message describing the error.
- A boolean that indicates success or failure.
A value of false, the HTTP code, and a JSON error message are returned when a call to an endpoint fails.
All client libraries provide an "is successful" boolean indicating if the call to the endpoint was successful, an HTTP status code indicating the call's status, and a JSON error message if a call is unsuccessful.
Use the methods provided to ensure proper error handling when calling any DynamicPDF API endpoints.
Use the following logic to ensure a call's success.
if
pdf-response call is successfull
then
process response
else
handle JSON error response
dlex-layout Endpoint Example
Let's illustrate exception handling by considering an example that calls the dlex-layout
endpoint. The dlex-layout
endpoint combines a DLEX file and JSON layout data document that contains the data used by the DLEX to generate a PDF report.
Obtain this example using the error-handling-example
sample available from your CloudAPI Cloud Storage using the File Manager.
SimpleReportCoverPage.dlex
SimpleResportWithCoverPage.json
NorthwindLogo.gif
Consider the following JSON layout data SimpleReportWithCoverPage.json
used by a DLEX file to generate a report.
{
'ReportCreatedFor': 'Alex Smith',
'Products':
[
{
'ProductID': 17,
'ProductName': 'Alice Mutton',
'QuantityPerUnit': '20 - 1 kg tins',
'UnitPrice': 39,
'Discontinued': true
},
{
'ProductID': 3,
'ProductName': 'Aniseed Syrup',
'QuantityPerUnit': '12 - 550 ml bottles',
'UnitPrice': 10,
'Discontinued': false
}
]
}
The following example uses cURL to generate the PDF report
curl https://api.dpdf.io/v1.0/dlex-layout
-H "Authorization:Bearer DP.xxx-api-key-xxx"
-F "DlexPath=samples/error-handling-example/SimpleReportWithCoverPage.dlex"
-F "LayoutData=@C:/temp/dynamicpdf-api-samples/error-handling-example/SimpleReportWithCoverPage.json"
-o simple-report.pdf
The report produced is a simple report and cover page.
Now let's illustrate error handling by introducing errors to the dataset. Error handling is described below when using cURL, C#, Java, NodeJS, PHP, Go, and Python.
Error Handling
- cURL
- C# (.NET)
- Java
- Node.js
- PHP
- Go
- Python
In this first example, the call to the dlex-layout endpoint omits the Authorization
key.
curl https://api.dpdf.io/v1.0/dlex-layout
-H "Authorization:Bearer DP.xxx-api-key-xxx"
-F "DlexPath=samples/error-handling-example/SimpleReportWithCoverPage.dlex"
-F "LayoutData=@C:/temp/dynamicpdf-api-samples/error-handling-example/SimpleReportWithCoverPage.json"
-o simple-report.pdf
After running the command, API returns an error JSON response. But cURL writes the error message to the file specified (simple-report.pdf
). An error occurs if you attempt to open the PDF in Acrobat.
Opening the file in a text editor reveals the JSON error as text. The omitted Authorization
key results in the following error message.
{
"type":"https://tools.ietf.org/html/rfc7235#section-3.1",
"title":"Unauthorized",
"status":401,
"traceId":"00-ec2b7a11f140abf9988acdcad41372d7-c8425194c618c6e9-00"
}
cURL writes the DynamicPDF API's JSON to the file specified by the cURL command.
This next example adds an Authorization
key but has an incorrect DlexPath
.
curl https://api.dpdf.io/v1.0/dlex-layout
-H "Authorization:Bearer DP.xxx-api-key-xxx"
-F "DlexPath=samples/wrong-path/SimpleReportWithCoverPage.dlex"
-F "LayoutData=@C:/temp/dynamicpdf-api-samples/error-handling-example/SimpleReportWithCoverPage.json"
-o simple-report.pdf
Executing the cURL command results in the following error message.
{
"id":"f0b5d157-f9b0-4a89-bd20-eab54df59271",
"message":"Array cannot be null. (Parameter 'bytes')"
}
The final example, modifies the JSON layout data presented above to be invalid.
false}xx]}
Executing the cURL command results in the following error message.
{
"id":"2f7e6e47-a60a-4e84-937f-268ca90ce6b0",
"message":"After parsing a value an unexpected character was encountered: x. Path 'Products[1]', line 1, position 296."
}
The DynamicPDF API's C# client library uses the PdfResponse
class to call an endpoint and get the results. The PdfResponse
extends the Response
class, which has the following methods for returning the endpoint's response status.
using System;
using System.Net;
namespace DynamicPDF.Api
{
public class Response
{
public Response();
// The response's status.
public bool IsSuccessful { get; }
// The error message.
public string ErrorMessage { get; }
// The error id.
public Guid? ErrorId { get; }
//The status code.
public HttpStatusCode StatusCode { get; }
// The error json.
public string ErrorJson { get; }
}
}
Currently only the IsSuccessful
, StatusCode
and ErrorJson
are returned from the Response
.
The following example illustrates adding simple error handling to calling the dlex-layout
endpoint. First, after calling the endpoint, it checks whether the response was successful. If unsuccessful, it writes the error JSON to the console.
public static void Run(String apiKey, String basePath)
{
LayoutDataResource layoutData = new LayoutDataResource(basePath + "SimpleReportWithCoverPage.json");
DlexLayout dlexEndpoint = new DlexLayout("samples/error-handling-example/SimpleReportWithCoverPage.dlex", layoutData);
dlexEndpoint.ApiKey = apiKey;
PdfResponse response = dlexEndpoint.Process();
Console.WriteLine("StatusCode: " + (int)response.StatusCode + " " + response.StatusCode);
if (response.IsSuccessful)
{
File.WriteAllBytes(basePath + "csharp-dlex-layout-example-output.pdf", response.Content);
}
else
{
Console.WriteLine("ErrorJson: " + response.ErrorJson);
}
}
When the error occurs, it displays an error. The following error illustrates calling the endpoint with an invalid Authorization
key.
The following error is returned when calling the endpoint with an invalid Authorization
key.
StatusCode: 401 Unauthorized
ErrorJson: {"type":"https://tools.ietf.org/html/rfc7235#section-3.1","title":"Unauthorized","status":401,"traceId":"00-f272244464b023b112bf91f871473837-ae20624071bafaef-00"}
Calling the endpoint with invalid layout data returns a different error message.
StatusCode: 500 InternalServerError
ErrorJson: {"id":"06c02dcb-f3dd-4cbd-9208-d31ec334fe09","message":"After parsing a value an unexpected character was encountered: x. Path 'Products[1]', line 1, position 296."}
The DynamicPDF API's Java client library uses the PdfResponse
class to call an endpoint and get the results. The PdfResponse
extends the Response
class, which has the following methods for returning the endpoint's response status.
package com.dynamicpdf.api;
import java.util.UUID;
/**
* Represents the base class for response.
*/
public class Response {
private boolean isSuccessful;
private String errorJson;
private String errorMessage;
private UUID errorId = null;
private int statusCode;
/**
* Gets the boolean, indicating the response's status.
* @return The boolean, indicating the response's status.
*/
public boolean getIsSuccessful() {
return isSuccessful;
}
void setIsSuccessful(boolean value) {
isSuccessful = value;
}
/**
* Gets the error message.
* @return The error message.
*/
public String getErrorMessage() {
return errorMessage;
}
void setErrorMessage(String value) {
errorMessage = value;
}
/**
* Gets the error id.
* @return The error id.
*/
public UUID getErrorId() {
return errorId;
}
void setErrorId(UUID value) {
errorId = value;
}
/**
* Gets the status code.
* @return The status code.
*/
public int getStatusCode() {
return statusCode;
}
void setStatusCode(int value) {
statusCode = value;
}
/**
* Gets the error json.
* @return The error json.
*/
public String getErrorJson() {
return errorJson;
}
void setErrorJson(String value) {
errorJson = value;
}
}
Currently only getIsSuccessful
, getStatusCode
and getErrorJson
are returned from the Response
.
The following example illustrates adding simple error handling to calling the dlex-layout
endpoint. First, after calling the endpoint, it checks to see if the response was successful. If unsuccessful, it writes the error JSON to the console.
public static void Run(String apiKey, String basePath) {
LayoutDataResource layoutData = new LayoutDataResource(basePath + "SimpleReportWithCoverPage.json");
DlexLayout dlexEndpoint = new DlexLayout("samples/error-handling-example/SimpleReportWithCoverPage.dlex", layoutData);
dlexEndpoint.setApiKey(apiKey);
PdfResponse response = dlexEndpoint.process();
System.out.println("Status: " + response.getStatusCode());
if (response.getIsSuccessful()) {
try {
FileUtils.writeByteArrayToFile(new File(basePath + "/create-pdf-dlex-layout-output.pdf"), (byte[]) response.getContent());
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println(response.getErrorJson());
}
}
StatusCode: 401 Unauthorized
ErrorJson: {"type":"https://tools.ietf.org/html/rfc7235#section-3.1","title":"Unauthorized","status":401,"traceId":"00-f272244464b023b112bf91f871473837-ae20624071bafaef-00"}
The DynamicPDF API's NodeJS client library uses the PdfResponse
class to call an endpoint and get the results. The PdfResponse
extends the Response
class, which has the following properties for returning the endpoint's response status.
/** Represents the base class for response.*/
export class Response {
/** Gets the boolean, indicating the response's status. */
isSuccessful;
/** Gets the error message. */
errorMessage;
/** Gets the error id. */
errorId
/** Gets the status code. */
statusCode
/** Gets the error json. */
errorJson;
}
Currently only the statusCode
and errorJson
are returned from the Response
.
static async Run() {
var layoutData = new LayoutDataResource("C:/temp/dynamicpdf-api-samples/error-handling-example/SimpleReportWithCoverPage.json");
var dlexEndpoint = new DlexLayout("samples/error-handling-example/SimpleReportWithCoverPage.dlex", layoutData);
dlexEndpoint.ApiKey = "DP.xxx-api-key-xxx";
var res = await dlexEndpoint.process();
console.log(response.statusCode);
if (res.isSuccessful) {
var outFile = "C:/temp/dynamicpdf-api-samples/errror-handling-example/nodejs-dlex-layout-example-output.pdf";
var outStream = fs.createWriteStream(outFile);
outStream.write(res.content);
outStream.close();
} else {
console.log("ErrorId: " + response.errorId);
console.log("ErrorMsg: " + response.errorMessage);
console.log(response.errorJson);
}
}
The DynamicPDF API's PHP client library uses the Response
class to call an endpoint and get the results. The Response
class has the following properties for returning the endpoint's response status.
<?php
namespace DynamicPDF\Api;
/**
*
* Represents the base class for response.
*
*/
class Response
{
/**
*
* Gets the boolean, indicating the response's status.
*
*/
public $IsSuccessful;
/**
*
* Gets the error message.
*
*/
public $ErrorMessage;
/**
*
* Gets the error id.
*
*/
public $ErrorId;
/**
*
* Gets the status code.
*
*/
public $StatusCode;
/**
*
* Gets the error json.
*
*/
public $ErrorJson;
}
The following example illustrates an example with added error handling. If successful it saves the response content as a file, otherwise it displays the error to the console.
public static function Run()
{
$layoutData = new LayoutDataResource(DlexLayoutExample::$BasePath . "SimpleReportWithCoverPage.json");
$dlexEndpoint = new DlexLayout("samples/error-handling-example/SimpleReportWithCoverPage.dlex", $layoutData);
$dlexEndpoint->ApiKey = DlexLayoutExample::$ApiKey;
$response = $dlexEndpoint->Process();
echo("Http Status: " . $response->StatusCode . "\n");
if($response->IsSuccessful) {
file_put_contents(DlexLayoutExample::$BasePath . "php-dlex-layout-example-output.pdf", $response->Content);
} else {
echo("ErrorId: " . $response->ErrorId . "\n");
echo("ErrorMsg:" . $response->ErrorMessage . "\n");
echo("ErrorJSON: " . $response->ErrorJson . "\n");
}
}
Calling the endpoint without an authorization key, for example, results in the following error.
Http Status: 401
ErrorId: 00-f670256acdc97676aa633c97957ab88f-93af0f11b017a016-00
ErrorMsg:Unauthorized
ErrorJSON: {"type":"https://tools.ietf.org/html/rfc7235#section-3.1","title":"Unauthorized","status":401,"traceId":"00-f670256acdc97676aa633c97957ab88f-93af0f11b017a016-00"}
The DynamicPDF API's Go client library uses the Response
class to call an endpoint and get the results. The Response
class has the following properties for returning the endpoint's response status.
type Response interface {
ClientError() error
IsSuccessful() bool
ErrorMessage() string
ErrorId() uuid.UUID
StatusCode() int
ErrorJson() string
}
// Response from server
type response struct {
Response
clientError error
isSuccessful bool
errorMessage string
errorId uuid.UUID
statusCode int
errorJson string
content *bytes.Buffer
}
var _ Response = (*response)(nil)
// Gets the error json.
func (r *response) ClientError() error {
return r.clientError
}
// Gets the boolean, indicating the response's status.
func (r *response) IsSuccessful() bool {
return r.isSuccessful
}
// Gets the error message.
func (r *response) ErrorMessage() string {
return r.errorMessage
}
// Gets the error id.
func (r *response) ErrorId() uuid.UUID {
return r.errorId
}
// Gets the status code.
func (r *response) StatusCode() int {
return r.statusCode
}
// Gets the error json.
func (r *response) ErrorJson() string {
return r.errorJson
}
The following example illustrates an example with added error handling. If successful it saves the response content as a file, otherwise it displays the error to the console.
func main() {
layoutDataResource := resource.NewLayoutDataResource("c:/temp/dynamicpdf-api-samples/error-handling-example/SimpleReportWithCoverPage.json", "SimpleReportWithCoverPage.json")
layoutData := endpoint.NewDlexEndpoint("samples/error-handling-example/SimpleReportWithCoverPage.dlex", layoutDataResource)
layoutData.Endpoint.BaseUrl = "https://api.dpdf.io/"
layoutData.Endpoint.ApiKey = "DP.xxx-api-key-xxx"
resp := layoutData.Process()
res := <-resp
fmt.Println("HTTP Response: " + strconv.Itoa(res.StatusCode()))
if res.IsSuccessful() == true {
os.WriteFile("c:/temp/dynamicpdf-api-samples/dlex-layout-example/output.pdf", res.Content().Bytes(), os.ModeType)
} else {
fmt.Println("errorId: " + res.ErrorId().String())
fmt.Println("errorMsg: " + res.ErrorMessage())
fmt.Println("Failed with error json: " + res.ErrorJson())
}
}
Calling the endpoint without an authorization key, for example, results in the following error.
HTTP Response: 401
errorId: 00000000-0000-0000-0000-000000000000
errorMsg: 401 Unauthorized
Failed with error json: {"type":"https://tools.ietf.org/html/rfc7235#section-3.1","title":"Unauthorized","status":401,"traceId":"00-990103f2eb4b2324af3d0e03f6357eb4-0f27716c0e274c47-00"}
The DynamicPDF API's Python client library uses the Response
class to call an endpoint and get the results. The Response
class has the following properties for returning the endpoint's response status.
class Response:
'''Represents the base class for response'''
def __init__(self):
self.IsSuccessful = None
self.ErrorMessage = None
self.ErrorId = None
self.StatusCode = None
self.ErrorJson = None
The following example illustrates an example with added error handling. If successful it saves the response content as a file, otherwise it displays the error to the console.
if response.is_successful:
with open("Outputs/create-pdf-dlex-output.pdf", "wb") as output_file:
output_file.write(response.content)
else:
print(response.error_id)
print(response.error_message)
print(response.error_json)