Integrating DHL Express API in Java

DHL Express provides comprehensive APIs for shipping, tracking, and logistics operations. This guide covers implementing DHL Express API integration in Java for shipping quotes, label generation, tracking, and more.

Architecture Overview

Java Application → DHL Express API Client → DHL Web Services
→ SOAP/REST Clients → Various DHL Services
→ Authentication → Rate Quotes → Shipment Creation → Tracking

Prerequisites and Setup

Maven Dependencies

<properties>
<cxf.version>3.5.5</cxf.version>
<jackson.version>2.15.2</jackson.version>
</properties>
<dependencies>
<!-- REST Client -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SOAP Client -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<!-- JSON Processing -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- HTTP Client -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.2.1</version>
</dependency>
<!-- XML Binding -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.0</version>
</dependency>
</dependencies>

Configuration Properties

# DHL Express API Configuration
dhl.api.base-url=https://express.api.dhl.com/mydhlapi
dhl.api.test-base-url=https://express.api.dhl.com/mydhlapi/test
dhl.api.username=your-dhl-username
dhl.api.password=your-dhl-password
dhl.api.account-number=123456789
# SOAP Services
dhl.soap.rate-url=https://wsbexpress.dhl.com/gbl/expressRateBook?WSDL
dhl.soap.shipment-url=https://wsbexpress.dhl.com/sndpt/expressRateBook?WSDL
# Connection Settings
dhl.connection.timeout=30000
dhl.connection.request-timeout=60000
dhl.connection.max-retries=3

Core DHL API Client

1. Configuration Classes

package com.yourapp.dhl.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "dhl.api")
public class DHLConfig {
private String baseUrl;
private String testBaseUrl;
private String username;
private String password;
private String accountNumber;
private int connectionTimeout;
private int requestTimeout;
private int maxRetries;
// Getters and Setters
public String getBaseUrl() { return baseUrl; }
public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; }
public String getTestBaseUrl() { return testBaseUrl; }
public void setTestBaseUrl(String testBaseUrl) { this.testBaseUrl = testBaseUrl; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public String getAccountNumber() { return accountNumber; }
public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; }
public int getConnectionTimeout() { return connectionTimeout; }
public void setConnectionTimeout(int connectionTimeout) { this.connectionTimeout = connectionTimeout; }
public int getRequestTimeout() { return requestTimeout; }
public void setRequestTimeout(int requestTimeout) { this.requestTimeout = requestTimeout; }
public int getMaxRetries() { return maxRetries; }
public void setMaxRetries(int maxRetries) { this.maxRetries = maxRetries; }
}

2. Base REST Client

package com.yourapp.dhl.client;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yourapp.dhl.config.DHLConfig;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.classic.methods.*;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
@Component
public class DHLRestClient {
private static final Logger logger = LoggerFactory.getLogger(DHLRestClient.class);
private final DHLConfig dhlConfig;
private final HttpClient httpClient;
private final ObjectMapper objectMapper;
public DHLRestClient(DHLConfig dhlConfig, ObjectMapper objectMapper) {
this.dhlConfig = dhlConfig;
this.objectMapper = objectMapper;
this.httpClient = HttpClientBuilder.create().build();
}
/**
* Execute GET request to DHL API
*/
public <T> T get(String endpoint, Class<T> responseType) {
try {
String url = dhlConfig.getBaseUrl() + endpoint;
HttpGet request = new HttpGet(url);
setCommonHeaders(request);
return executeRequest(request, responseType);
} catch (Exception e) {
logger.error("GET request failed for endpoint: {}", endpoint, e);
throw new DHLAPIException("DHL API request failed", e);
}
}
/**
* Execute POST request to DHL API
*/
public <T> T post(String endpoint, Object requestBody, Class<T> responseType) {
try {
String url = dhlConfig.getBaseUrl() + endpoint;
HttpPost request = new HttpPost(url);
setCommonHeaders(request);
String jsonBody = objectMapper.writeValueAsString(requestBody);
StringEntity entity = new StringEntity(jsonBody, StandardCharsets.UTF_8);
entity.setContentType(MediaType.APPLICATION_JSON_VALUE);
request.setEntity(entity);
return executeRequest(request, responseType);
} catch (Exception e) {
logger.error("POST request failed for endpoint: {}", endpoint, e);
throw new DHLAPIException("DHL API request failed", e);
}
}
/**
* Execute PUT request to DHL API
*/
public <T> T put(String endpoint, Object requestBody, Class<T> responseType) {
try {
String url = dhlConfig.getBaseUrl() + endpoint;
HttpPut request = new HttpPut(url);
setCommonHeaders(request);
String jsonBody = objectMapper.writeValueAsString(requestBody);
StringEntity entity = new StringEntity(jsonBody, StandardCharsets.UTF_8);
entity.setContentType(MediaType.APPLICATION_JSON_VALUE);
request.setEntity(entity);
return executeRequest(request, responseType);
} catch (Exception e) {
logger.error("PUT request failed for endpoint: {}", endpoint, e);
throw new DHLAPIException("DHL API request failed", e);
}
}
private <T> T executeRequest(HttpUriRequest request, Class<T> responseType) throws Exception {
return httpClient.execute(request, response -> {
int statusCode = response.getCode();
String responseBody = EntityUtils.toString(response.getEntity());
if (statusCode >= 200 && statusCode < 300) {
return objectMapper.readValue(responseBody, responseType);
} else {
logger.error("DHL API error - Status: {}, Response: {}", statusCode, responseBody);
throw new DHLAPIException("DHL API returned error: " + statusCode + " - " + responseBody);
}
});
}
private void setCommonHeaders(HttpUriRequest request) {
// Basic Authentication
String auth = dhlConfig.getUsername() + ":" + dhlConfig.getPassword();
String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));
request.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + encodedAuth);
request.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
request.setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
request.setHeader("Message-Reference", generateMessageReference());
request.setHeader("Message-Reference-Date", java.time.OffsetDateTime.now().toString());
}
private String generateMessageReference() {
return java.util.UUID.randomUUID().toString().substring(0, 32);
}
public static class DHLAPIException extends RuntimeException {
public DHLAPIException(String message) { super(message); }
public DHLAPIException(String message, Throwable cause) { super(message, cause); }
}
}

Core DHL Services

1. Rate Quote Service

package com.yourapp.dhl.service;
import com.yourapp.dhl.client.DHLRestClient;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.*;
@Service
public class DHLRateService {
private final DHLRestClient restClient;
public DHLRateService(DHLRestClient restClient) {
this.restClient = restClient;
}
/**
* Get shipping rates for a shipment
*/
public RateResponse getRates(RateRequest rateRequest) {
String endpoint = "/rates";
return restClient.post(endpoint, rateRequest, RateResponse.class);
}
/**
* Get rates for multiple products
*/
public RateResponse getRatesMultipleProducts(MultiProductRateRequest request) {
String endpoint = "/rates";
return restClient.post(endpoint, request, RateResponse.class);
}
/**
* Get estimated delivery date
*/
public DeliveryDateResponse getEstimatedDeliveryDate(DeliveryDateRequest request) {
String endpoint = "/delivery-date";
return restClient.post(endpoint, request, DeliveryDateResponse.class);
}
// Request and Response classes
public static class RateRequest {
private CustomerDetails customerDetails;
private List<Packages> packages;
private String plannedShippingDate;
private String unitOfMeasurement = "metric";
private boolean isCustomsDeclarable = false;
private String shipmentPurpose = "COMMERCIAL";
// Getters and Setters
public CustomerDetails getCustomerDetails() { return customerDetails; }
public void setCustomerDetails(CustomerDetails customerDetails) { this.customerDetails = customerDetails; }
public List<Packages> getPackages() { return packages; }
public void setPackages(List<Packages> packages) { this.packages = packages; }
public String getPlannedShippingDate() { return plannedShippingDate; }
public void setPlannedShippingDate(String plannedShippingDate) { this.plannedShippingDate = plannedShippingDate; }
public String getUnitOfMeasurement() { return unitOfMeasurement; }
public void setUnitOfMeasurement(String unitOfMeasurement) { this.unitOfMeasurement = unitOfMeasurement; }
public boolean isCustomsDeclarable() { return isCustomsDeclarable; }
public void setCustomsDeclarable(boolean customsDeclarable) { isCustomsDeclarable = customsDeclarable; }
public String getShipmentPurpose() { return shipmentPurpose; }
public void setShipmentPurpose(String shipmentPurpose) { this.shipmentPurpose = shipmentPurpose; }
}
public static class CustomerDetails {
private ShipperDetails shipperDetails;
private ReceiverDetails receiverDetails;
public ShipperDetails getShipperDetails() { return shipperDetails; }
public void setShipperDetails(ShipperDetails shipperDetails) { this.shipperDetails = shipperDetails; }
public ReceiverDetails getReceiverDetails() { return receiverDetails; }
public void setReceiverDetails(ReceiverDetails receiverDetails) { this.receiverDetails = receiverDetails; }
}
public static class ShipperDetails {
private PostalAddress postalAddress;
public PostalAddress getPostalAddress() { return postalAddress; }
public void setPostalAddress(PostalAddress postalAddress) { this.postalAddress = postalAddress; }
}
public static class ReceiverDetails {
private PostalAddress postalAddress;
public PostalAddress getPostalAddress() { return postalAddress; }
public void setPostalAddress(PostalAddress postalAddress) { this.postalAddress = postalAddress; }
}
public static class PostalAddress {
private String postalCode;
private String cityName;
private String countryCode;
private String addressLine1;
private String addressLine2;
private String stateOrProvinceCode;
// Getters and Setters
public String getPostalCode() { return postalCode; }
public void setPostalCode(String postalCode) { this.postalCode = postalCode; }
public String getCityName() { return cityName; }
public void setCityName(String cityName) { this.cityName = cityName; }
public String getCountryCode() { return countryCode; }
public void setCountryCode(String countryCode) { this.countryCode = countryCode; }
public String getAddressLine1() { return addressLine1; }
public void setAddressLine1(String addressLine1) { this.addressLine1 = addressLine1; }
public String getAddressLine2() { return addressLine2; }
public void setAddressLine2(String addressLine2) { this.addressLine2 = addressLine2; }
public String getStateOrProvinceCode() { return stateOrProvinceCode; }
public void setStateOrProvinceCode(String stateOrProvinceCode) { this.stateOrProvinceCode = stateOrProvinceCode; }
}
public static class Packages {
private double weight;
private Dimensions dimensions;
private String description;
// Getters and Setters
public double getWeight() { return weight; }
public void setWeight(double weight) { this.weight = weight; }
public Dimensions getDimensions() { return dimensions; }
public void setDimensions(Dimensions dimensions) { this.dimensions = dimensions; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
}
public static class Dimensions {
private double length;
private double width;
private double height;
public Dimensions(double length, double width, double height) {
this.length = length;
this.width = width;
this.height = height;
}
// Getters and Setters
public double getLength() { return length; }
public void setLength(double length) { this.length = length; }
public double getWidth() { return width; }
public void setWidth(double width) { this.width = width; }
public double getHeight() { return height; }
public void setHeight(double height) { this.height = height; }
}
public static class RateResponse {
private List<Product> products;
private String exchangeRate;
private boolean customsDeclarable;
// Getters and Setters
public List<Product> getProducts() { return products; }
public void setProducts(List<Product> products) { this.products = products; }
public String getExchangeRate() { return exchangeRate; }
public void setExchangeRate(String exchangeRate) { this.exchangeRate = exchangeRate; }
public boolean isCustomsDeclarable() { return customsDeclarable; }
public void setCustomsDeclarable(boolean customsDeclarable) { this.customsDeclarable = customsDeclarable; }
}
public static class Product {
private String productName;
private String productCode;
private List<TotalPrice> totalPrice;
private List<TotalPriceBreakdown> totalPriceBreakdown;
private String pickupCapabilities;
private String deliveryCapabilities;
private List<DetailedPriceBreakdown> detailedPriceBreakdown;
// Getters and Setters
public String getProductName() { return productName; }
public void setProductName(String productName) { this.productName = productName; }
public String getProductCode() { return productCode; }
public void setProductCode(String productCode) { this.productCode = productCode; }
public List<TotalPrice> getTotalPrice() { return totalPrice; }
public void setTotalPrice(List<TotalPrice> totalPrice) { this.totalPrice = totalPrice; }
public List<TotalPriceBreakdown> getTotalPriceBreakdown() { return totalPriceBreakdown; }
public void setTotalPriceBreakdown(List<TotalPriceBreakdown> totalPriceBreakdown) { this.totalPriceBreakdown = totalPriceBreakdown; }
public String getPickupCapabilities() { return pickupCapabilities; }
public void setPickupCapabilities(String pickupCapabilities) { this.pickupCapabilities = pickupCapabilities; }
public String getDeliveryCapabilities() { return deliveryCapabilities; }
public void setDeliveryCapabilities(String deliveryCapabilities) { this.deliveryCapabilities = deliveryCapabilities; }
public List<DetailedPriceBreakdown> getDetailedPriceBreakdown() { return detailedPriceBreakdown; }
public void setDetailedPriceBreakdown(List<DetailedPriceBreakdown> detailedPriceBreakdown) { this.detailedPriceBreakdown = detailedPriceBreakdown; }
}
public static class TotalPrice {
private String currencyType;
private double price;
private double priceCurrency;
// Getters and Setters
public String getCurrencyType() { return currencyType; }
public void setCurrencyType(String currencyType) { this.currencyType = currencyType; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
public double getPriceCurrency() { return priceCurrency; }
public void setPriceCurrency(double priceCurrency) { this.priceCurrency = priceCurrency; }
}
public static class TotalPriceBreakdown {
private String currencyType;
private double price;
private String typeCode;
// Getters and Setters
public String getCurrencyType() { return currencyType; }
public void setCurrencyType(String currencyType) { this.currencyType = currencyType; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
public String getTypeCode() { return typeCode; }
public void setTypeCode(String typeCode) { this.typeCode = typeCode; }
}
public static class DetailedPriceBreakdown {
private String currencyType;
private double price;
private String typeCode;
private String serviceCode;
// Getters and Setters
public String getCurrencyType() { return currencyType; }
public void setCurrencyType(String currencyType) { this.currencyType = currencyType; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
public String getTypeCode() { return typeCode; }
public void setTypeCode(String typeCode) { this.typeCode = typeCode; }
public String getServiceCode() { return serviceCode; }
public void setServiceCode(String serviceCode) { this.serviceCode = serviceCode; }
}
public static class DeliveryDateRequest {
private String shippingDate;
private String destinationPostalCode;
private String destinationCountryCode;
private String serviceProductCode;
private boolean isCustomsDeclarable = false;
// Getters and Setters
public String getShippingDate() { return shippingDate; }
public void setShippingDate(String shippingDate) { this.shippingDate = shippingDate; }
public String getDestinationPostalCode() { return destinationPostalCode; }
public void setDestinationPostalCode(String destinationPostalCode) { this.destinationPostalCode = destinationPostalCode; }
public String getDestinationCountryCode() { return destinationCountryCode; }
public void setDestinationCountryCode(String destinationCountryCode) { this.destinationCountryCode = destinationCountryCode; }
public String getServiceProductCode() { return serviceProductCode; }
public void setServiceProductCode(String serviceProductCode) { this.serviceProductCode = serviceProductCode; }
public boolean isCustomsDeclarable() { return isCustomsDeclarable; }
public void setCustomsDeclarable(boolean customsDeclarable) { isCustomsDeclarable = customsDeclarable; }
}
public static class DeliveryDateResponse {
private List<DeliveryProduct> deliveryProducts;
public List<DeliveryProduct> getDeliveryProducts() { return deliveryProducts; }
public void setDeliveryProducts(List<DeliveryProduct> deliveryProducts) { this.deliveryProducts = deliveryProducts; }
}
public static class DeliveryProduct {
private String productCode;
private String productName;
private List<DeliveryDate> deliveryDate;
// Getters and Setters
public String getProductCode() { return productCode; }
public void setProductCode(String productCode) { this.productCode = productCode; }
public String getProductName() { return productName; }
public void setProductName(String productName) { this.productName = productName; }
public List<DeliveryDate> getDeliveryDate() { return deliveryDate; }
public void setDeliveryDate(List<DeliveryDate> deliveryDate) { this.deliveryDate = deliveryDate; }
}
public static class DeliveryDate {
private String typeCode;
private String date;
private String time;
// Getters and Setters
public String getTypeCode() { return typeCode; }
public void setTypeCode(String typeCode) { this.typeCode = typeCode; }
public String getDate() { return date; }
public void setDate(String date) { this.date = date; }
public String getTime() { return time; }
public void setTime(String time) { this.time = time; }
}
public static class MultiProductRateRequest {
private String accountNumber;
private String originCountryCode;
private String originPostalCode;
private String destinationCountryCode;
private String destinationPostalCode;
private String weight;
private String length;
private String width;
private String height;
private String plannedShippingDate;
private boolean isCustomsDeclarable;
private String unitOfMeasurement;
private boolean nextBusinessDay;
private boolean strictValidation;
// Getters and Setters
public String getAccountNumber() { return accountNumber; }
public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; }
public String getOriginCountryCode() { return originCountryCode; }
public void setOriginCountryCode(String originCountryCode) { this.originCountryCode = originCountryCode; }
public String getOriginPostalCode() { return originPostalCode; }
public void setOriginPostalCode(String originPostalCode) { this.originPostalCode = originPostalCode; }
public String getDestinationCountryCode() { return destinationCountryCode; }
public void setDestinationCountryCode(String destinationCountryCode) { this.destinationCountryCode = destinationCountryCode; }
public String getDestinationPostalCode() { return destinationPostalCode; }
public void setDestinationPostalCode(String destinationPostalCode) { this.destinationPostalCode = destinationPostalCode; }
public String getWeight() { return weight; }
public void setWeight(String weight) { this.weight = weight; }
public String getLength() { return length; }
public void setLength(String length) { this.length = length; }
public String getWidth() { return width; }
public void setWidth(String width) { this.width = width; }
public String getHeight() { return height; }
public void setHeight(String height) { this.height = height; }
public String getPlannedShippingDate() { return plannedShippingDate; }
public void setPlannedShippingDate(String plannedShippingDate) { this.plannedShippingDate = plannedShippingDate; }
public boolean isCustomsDeclarable() { return isCustomsDeclarable; }
public void setCustomsDeclarable(boolean customsDeclarable) { isCustomsDeclarable = customsDeclarable; }
public String getUnitOfMeasurement() { return unitOfMeasurement; }
public void setUnitOfMeasurement(String unitOfMeasurement) { this.unitOfMeasurement = unitOfMeasurement; }
public boolean isNextBusinessDay() { return nextBusinessDay; }
public void setNextBusinessDay(boolean nextBusinessDay) { this.nextBusinessDay = nextBusinessDay; }
public boolean isStrictValidation() { return strictValidation; }
public void setStrictValidation(boolean strictValidation) { this.strictValidation = strictValidation; }
}
}

2. Shipment Service

package com.yourapp.dhl.service;
import com.yourapp.dhl.client.DHLRestClient;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
public class DHLShipmentService {
private final DHLRestClient restClient;
public DHLShipmentService(DHLRestClient restClient) {
this.restClient = restClient;
}
/**
* Create a new shipment
*/
public ShipmentResponse createShipment(ShipmentRequest shipmentRequest) {
String endpoint = "/shipments";
return restClient.post(endpoint, shipmentRequest, ShipmentResponse.class);
}
/**
* Get shipment details by tracking number
*/
public ShipmentResponse getShipment(String trackingNumber) {
String endpoint = "/shipments/" + trackingNumber;
return restClient.get(endpoint, ShipmentResponse.class);
}
/**
* Cancel a shipment
*/
public CancelShipmentResponse cancelShipment(String trackingNumber) {
String endpoint = "/shipments/" + trackingNumber;
return restClient.delete(endpoint, CancelShipmentResponse.class);
}
/**
* Get shipment image (label)
*/
public byte[] getShipmentLabel(String trackingNumber, String format) {
try {
String endpoint = String.format("/shipments/%s/label?format=%s", trackingNumber, format);
// This would need a separate method to handle binary responses
return new byte[0]; // Implementation for binary response
} catch (Exception e) {
throw new DHLRestClient.DHLAPIException("Failed to get shipment label", e);
}
}
// Request and Response classes
public static class ShipmentRequest {
private String plannedShippingDateAndTime;
private Pickup pickup;
private List<Product> products;
private List<Package> packages;
private CustomerDetails customerDetails;
private String documentImagesFormat = "PDF";
private boolean getTransliteratedResponse = false;
private boolean estimatedDeliveryDate = true;
private boolean getAdditionalInformation = true;
// Getters and Setters
public String getPlannedShippingDateAndTime() { return plannedShippingDateAndTime; }
public void setPlannedShippingDateAndTime(String plannedShippingDateAndTime) { this.plannedShippingDateAndTime = plannedShippingDateAndTime; }
public Pickup getPickup() { return pickup; }
public void setPickup(Pickup pickup) { this.pickup = pickup; }
public List<Product> getProducts() { return products; }
public void setProducts(List<Product> products) { this.products = products; }
public List<Package> getPackages() { return packages; }
public void setPackages(List<Package> packages) { this.packages = packages; }
public CustomerDetails getCustomerDetails() { return customerDetails; }
public void setCustomerDetails(CustomerDetails customerDetails) { this.customerDetails = customerDetails; }
public String getDocumentImagesFormat() { return documentImagesFormat; }
public void setDocumentImagesFormat(String documentImagesFormat) { this.documentImagesFormat = documentImagesFormat; }
public boolean isGetTransliteratedResponse() { return getTransliteratedResponse; }
public void setGetTransliteratedResponse(boolean getTransliteratedResponse) { this.getTransliteratedResponse = getTransliteratedResponse; }
public boolean isEstimatedDeliveryDate() { return estimatedDeliveryDate; }
public void setEstimatedDeliveryDate(boolean estimatedDeliveryDate) { this.estimatedDeliveryDate = estimatedDeliveryDate; }
public boolean isGetAdditionalInformation() { return getAdditionalInformation; }
public void setGetAdditionalInformation(boolean getAdditionalInformation) { this.getAdditionalInformation = getAdditionalInformation; }
}
public static class Pickup {
private boolean isRequested = false;
public boolean isRequested() { return isRequested; }
public void setRequested(boolean requested) { isRequested = requested; }
}
public static class Product {
private String productCode;
public String getProductCode() { return productCode; }
public void setProductCode(String productCode) { this.productCode = productCode; }
}
public static class Package {
private String typeCode = "3BX";
private double weight;
private Dimensions dimensions;
private String description;
private String labelDescription;
private List<PackageReference> references;
// Getters and Setters
public String getTypeCode() { return typeCode; }
public void setTypeCode(String typeCode) { this.typeCode = typeCode; }
public double getWeight() { return weight; }
public void setWeight(double weight) { this.weight = weight; }
public Dimensions getDimensions() { return dimensions; }
public void setDimensions(Dimensions dimensions) { this.dimensions = dimensions; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getLabelDescription() { return labelDescription; }
public void setLabelDescription(String labelDescription) { this.labelDescription = labelDescription; }
public List<PackageReference> getReferences() { return references; }
public void setReferences(List<PackageReference> references) { this.references = references; }
}
public static class PackageReference {
private String value;
private String typeCode;
public String getValue() { return value; }
public void setValue(String value) { this.value = value; }
public String getTypeCode() { return typeCode; }
public void setTypeCode(String typeCode) { this.typeCode = typeCode; }
}
public static class ShipmentResponse {
private String url;
private String shipmentTrackingNumber;
private String cancelPickupUrl;
private String trackingUrl;
private String dispatchConfirmationNumber;
private List<PackageResult> packages;
private List<Document> documents;
private String shipmentDetails;
private String shipmentCharges;
// Getters and Setters
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public String getShipmentTrackingNumber() { return shipmentTrackingNumber; }
public void setShipmentTrackingNumber(String shipmentTrackingNumber) { this.shipmentTrackingNumber = shipmentTrackingNumber; }
public String getCancelPickupUrl() { return cancelPickupUrl; }
public void setCancelPickupUrl(String cancelPickupUrl) { this.cancelPickupUrl = cancelPickupUrl; }
public String getTrackingUrl() { return trackingUrl; }
public void setTrackingUrl(String trackingUrl) { this.trackingUrl = trackingUrl; }
public String getDispatchConfirmationNumber() { return dispatchConfirmationNumber; }
public void setDispatchConfirmationNumber(String dispatchConfirmationNumber) { this.dispatchConfirmationNumber = dispatchConfirmationNumber; }
public List<PackageResult> getPackages() { return packages; }
public void setPackages(List<PackageResult> packages) { this.packages = packages; }
public List<Document> getDocuments() { return documents; }
public void setDocuments(List<Document> documents) { this.documents = documents; }
public String getShipmentDetails() { return shipmentDetails; }
public void setShipmentDetails(String shipmentDetails) { this.shipmentDetails = shipmentDetails; }
public String getShipmentCharges() { return shipmentCharges; }
public void setShipmentCharges(String shipmentCharges) { this.shipmentCharges = shipmentCharges; }
}
public static class PackageResult {
private String referenceNumber;
private String trackingNumber;
private String trackingUrl;
public String getReferenceNumber() { return referenceNumber; }
public void setReferenceNumber(String referenceNumber) { this.referenceNumber = referenceNumber; }
public String getTrackingNumber() { return trackingNumber; }
public void setTrackingNumber(String trackingNumber) { this.trackingNumber = trackingNumber; }
public String getTrackingUrl() { return trackingUrl; }
public void setTrackingUrl(String trackingUrl) { this.trackingUrl = trackingUrl; }
}
public static class Document {
private String imageFormat;
private String content;
private String typeCode;
public String getImageFormat() { return imageFormat; }
public void setImageFormat(String imageFormat) { this.imageFormat = imageFormat; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
public String getTypeCode() { return typeCode; }
public void setTypeCode(String typeCode) { this.typeCode = typeCode; }
}
public static class CancelShipmentResponse {
private String url;
private String shipmentTrackingNumber;
private String cancelSuccess;
private String cancelMessage;
// Getters and Setters
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public String getShipmentTrackingNumber() { return shipmentTrackingNumber; }
public void setShipmentTrackingNumber(String shipmentTrackingNumber) { this.shipmentTrackingNumber = shipmentTrackingNumber; }
public String getCancelSuccess() { return cancelSuccess; }
public void setCancelSuccess(String cancelSuccess) { this.cancelSuccess = cancelSuccess; }
public String getCancelMessage() { return cancelMessage; }
public void setCancelMessage(String cancelMessage) { this.cancelMessage = cancelMessage; }
}
}

3. Tracking Service

package com.yourapp.dhl.service;
import com.yourapp.dhl.client.DHLRestClient;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
public class DHLTrackingService {
private final DHLRestClient restClient;
public DHLTrackingService(DHLRestClient restClient) {
this.restClient = restClient;
}
/**
* Track a single shipment by tracking number
*/
public TrackingResponse trackShipment(String trackingNumber) {
String endpoint = "/shipments/" + trackingNumber + "/tracking";
return restClient.get(endpoint, TrackingResponse.class);
}
/**
* Track multiple shipments
*/
public MultiTrackingResponse trackMultipleShipments(List<String> trackingNumbers) {
String trackingQuery = String.join(",", trackingNumbers);
String endpoint = "/shipments/tracking?trackingNumber=" + trackingQuery;
return restClient.get(endpoint, MultiTrackingResponse.class);
}
/**
* Get tracking events for a shipment
*/
public TrackingResponse getTrackingEvents(String trackingNumber, String level) {
String endpoint = String.format("/shipments/%s/tracking?level=%s", trackingNumber, level);
return restClient.get(endpoint, TrackingResponse.class);
}
// Request and Response classes
public static class TrackingResponse {
private String url;
private List<Shipment> shipments;
// Getters and Setters
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public List<Shipment> getShipments() { return shipments; }
public void setShipments(List<Shipment> shipments) { this.shipments = shipments; }
}
public static class Shipment {
private String id;
private String service;
private String origin;
private String destination;
private String status;
private String description;
private List<Event> events;
private List<Detail> details;
private List<ProofOfDelivery> proofOfDeliveries;
// Getters and Setters
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getService() { return service; }
public void setService(String service) { this.service = service; }
public String getOrigin() { return origin; }
public void setOrigin(String origin) { this.origin = origin; }
public String getDestination() { return destination; }
public void setDestination(String destination) { this.destination = destination; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public List<Event> getEvents() { return events; }
public void setEvents(List<Event> events) { this.events = events; }
public List<Detail> getDetails() { return details; }
public void setDetails(List<Detail> details) { this.details = details; }
public List<ProofOfDelivery> getProofOfDeliveries() { return proofOfDeliveries; }
public void setProofOfDeliveries(List<ProofOfDelivery> proofOfDeliveries) { this.proofOfDeliveries = proofOfDeliveries; }
}
public static class Event {
private String date;
private String time;
private String location;
private String description;
private String code;
private String serviceArea;
// Getters and Setters
public String getDate() { return date; }
public void setDate(String date) { this.date = date; }
public String getTime() { return time; }
public void setTime(String time) { this.time = time; }
public String getLocation() { return location; }
public void setLocation(String location) { this.location = location; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getCode() { return code; }
public void setCode(String code) { this.code = code; }
public String getServiceArea() { return serviceArea; }
public void setServiceArea(String serviceArea) { this.serviceArea = serviceArea; }
}
public static class Detail {
private String proofOfDeliverySignedAvailable;
private String proofOfDeliveryAvailable;
private String estimatedTimeOfDelivery;
private String estimatedDeliveryDate;
// Getters and Setters
public String getProofOfDeliverySignedAvailable() { return proofOfDeliverySignedAvailable; }
public void setProofOfDeliverySignedAvailable(String proofOfDeliverySignedAvailable) { this.proofOfDeliverySignedAvailable = proofOfDeliverySignedAvailable; }
public String getProofOfDeliveryAvailable() { return proofOfDeliveryAvailable; }
public void setProofOfDeliveryAvailable(String proofOfDeliveryAvailable) { this.proofOfDeliveryAvailable = proofOfDeliveryAvailable; }
public String getEstimatedTimeOfDelivery() { return estimatedTimeOfDelivery; }
public void setEstimatedTimeOfDelivery(String estimatedTimeOfDelivery) { this.estimatedTimeOfDelivery = estimatedTimeOfDelivery; }
public String getEstimatedDeliveryDate() { return estimatedDeliveryDate; }
public void setEstimatedDeliveryDate(String estimatedDeliveryDate) { this.estimatedDeliveryDate = estimatedDeliveryDate; }
}
public static class ProofOfDelivery {
private String url;
private String format;
private String value;
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public String getFormat() { return format; }
public void setFormat(String format) { this.format = format; }
public String getValue() { return value; }
public void setValue(String value) { this.value = value; }
}
public static class MultiTrackingResponse {
private List<Shipment> shipments;
private String url;
public List<Shipment> getShipments() { return shipments; }
public void setShipments(List<Shipment> shipments) { this.shipments = shipments; }
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
}
}

REST API Controllers

1. Shipping Controller

package com.yourapp.dhl.controller;
import com.yourapp.dhl.service.DHLRateService;
import com.yourapp.dhl.service.DHLShipmentService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("/api/dhl")
public class DHLShippingController {
private final DHLRateService rateService;
private final DHLShipmentService shipmentService;
public DHLShippingController(DHLRateService rateService, DHLShipmentService shipmentService) {
this.rateService = rateService;
this.shipmentService = shipmentService;
}
@PostMapping("/rates")
public ResponseEntity<?> getShippingRates(@RequestBody DHLRateService.RateRequest rateRequest) {
try {
DHLRateService.RateResponse response = rateService.getRates(rateRequest);
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.badRequest().body(
Map.of("error", "Failed to get rates", "message", e.getMessage())
);
}
}
@PostMapping("/shipments")
public ResponseEntity<?> createShipment(@RequestBody DHLShipmentService.ShipmentRequest shipmentRequest) {
try {
DHLShipmentService.ShipmentResponse response = shipmentService.createShipment(shipmentRequest);
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.badRequest().body(
Map.of("error", "Failed to create shipment", "message", e.getMessage())
);
}
}
@GetMapping("/shipments/{trackingNumber}")
public ResponseEntity<?> getShipment(@PathVariable String trackingNumber) {
try {
DHLShipmentService.ShipmentResponse response = shipmentService.getShipment(trackingNumber);
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.badRequest().body(
Map.of("error", "Failed to get shipment", "message", e.getMessage())
);
}
}
@DeleteMapping("/shipments/{trackingNumber}")
public ResponseEntity<?> cancelShipment(@PathVariable String trackingNumber) {
try {
DHLShipmentService.CancelShipmentResponse response = shipmentService.cancelShipment(trackingNumber);
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.badRequest().body(
Map.of("error", "Failed to cancel shipment", "message", e.getMessage())
);
}
}
@GetMapping("/shipments/{trackingNumber}/label")
public ResponseEntity<?> getShipmentLabel(@PathVariable String trackingNumber,
@RequestParam(defaultValue = "PDF") String format) {
try {
byte[] label = shipmentService.getShipmentLabel(trackingNumber, format);
return ResponseEntity.ok()
.header("Content-Type", "application/pdf")
.body(label);
} catch (Exception e) {
return ResponseEntity.badRequest().body(
Map.of("error", "Failed to get label", "message", e.getMessage())
);
}
}
}

2. Tracking Controller

package com.yourapp.dhl.controller;
import com.yourapp.dhl.service.DHLTrackingService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("/api/dhl/tracking")
public class DHLTrackingController {
private final DHLTrackingService trackingService;
public DHLTrackingController(DHLTrackingService trackingService) {
this.trackingService = trackingService;
}
@GetMapping("/{trackingNumber}")
public ResponseEntity<?> trackShipment(@PathVariable String trackingNumber) {
try {
DHLTrackingService.TrackingResponse response = trackingService.trackShipment(trackingNumber);
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.badRequest().body(
Map.of("error", "Failed to track shipment", "message", e.getMessage())
);
}
}
@GetMapping("/multiple")
public ResponseEntity<?> trackMultipleShipments(@RequestParam List<String> trackingNumbers) {
try {
DHLTrackingService.MultiTrackingResponse response = 
trackingService.trackMultipleShipments(trackingNumbers);
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.badRequest().body(
Map.of("error", "Failed to track shipments", "message", e.getMessage())
);
}
}
@GetMapping("/{trackingNumber}/events")
public ResponseEntity<?> getTrackingEvents(@PathVariable String trackingNumber,
@RequestParam(defaultValue = "all") String level) {
try {
DHLTrackingService.TrackingResponse response = 
trackingService.getTrackingEvents(trackingNumber, level);
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.badRequest().body(
Map.of("error", "Failed to get tracking events", "message", e.getMessage())
);
}
}
}

Utility Services

1. Address Validation Service

package com.yourapp.dhl.service;
import com.yourapp.dhl.client.DHLRestClient;
import org.springframework.stereotype.Service;
@Service
public class DHLAddressService {
private final DHLRestClient restClient;
public DHLAddressService(DHLRestClient restClient) {
this.restClient = restClient;
}
/**
* Validate shipping address
*/
public AddressValidationResponse validateAddress(AddressValidationRequest request) {
String endpoint = "/address-validate";
return restClient.post(endpoint, request, AddressValidationResponse.class);
}
/**
* Get service points near location
*/
public ServicePointResponse getServicePoints(ServicePointRequest request) {
String endpoint = "/service-points";
return restClient.get(endpoint, ServicePointResponse.class);
}
// Address validation request/response classes
public static class AddressValidationRequest {
private String countryCode;
private String postalCode;
private String cityName;
private String countyName;
private String provinceCode;
private String addressLine1;
private String addressLine2;
private String addressLine3;
// Getters and Setters
public String getCountryCode() { return countryCode; }
public void setCountryCode(String countryCode) { this.countryCode = countryCode; }
public String getPostalCode() { return postalCode; }
public void setPostalCode(String postalCode) { this.postalCode = postalCode; }
public String getCityName() { return cityName; }
public void setCityName(String cityName) { this.cityName = cityName; }
public String getCountyName() { return countyName; }
public void setCountyName(String countyName) { this.countryName = countyName; }
public String getProvinceCode() { return provinceCode; }
public void setProvinceCode(String provinceCode) { this.provinceCode = provinceCode; }
public String getAddressLine1() { return addressLine1; }
public void setAddressLine1(String addressLine1) { this.addressLine1 = addressLine1; }
public String getAddressLine2() { return addressLine2; }
public void setAddressLine2(String addressLine2) { this.addressLine2 = addressLine2; }
public String getAddressLine3() { return addressLine3; }
public void setAddressLine3(String addressLine3) { this.addressLine3 = addressLine3; }
}
public static class AddressValidationResponse {
private List<AddressSuggestion> suggestions;
private boolean valid;
private String validationMessage;
// Getters and Setters
public List<AddressSuggestion> getSuggestions() { return suggestions; }
public void setSuggestions(List<AddressSuggestion> suggestions) { this.suggestions = suggestions; }
public boolean isValid() { return valid; }
public void setValid(boolean valid) { this.valid = valid; }
public String getValidationMessage() { return validationMessage; }
public void setValidationMessage(String validationMessage) { this.validationMessage = validationMessage; }
}
public static class AddressSuggestion {
private String countryCode;
private String postalCode;
private String cityName;
private String countyName;
private String provinceCode;
private String addressLine1;
private String addressLine2;
private String addressLine3;
private String validationScore;
// Getters and Setters
public String getCountryCode() { return countryCode; }
public void setCountryCode(String countryCode) { this.countryCode = countryCode; }
public String getPostalCode() { return postalCode; }
public void setPostalCode(String postalCode) { this.postalCode = postalCode; }
public String getCityName() { return cityName; }
public void setCityName(String cityName) { this.cityName = cityName; }
public String getCountyName() { return countyName; }
public void setCountyName(String countyName) { this.countyName = countyName; }
public String getProvinceCode() { return provinceCode; }
public void setProvinceCode(String provinceCode) { this.provinceCode = provinceCode; }
public String getAddressLine1() { return addressLine1; }
public void setAddressLine1(String addressLine1) { this.addressLine1 = addressLine1; }
public String getAddressLine2() { return addressLine2; }
public void setAddressLine2(String addressLine2) { this.addressLine2 = addressLine2; }
public String getAddressLine3() { return addressLine3; }
public void setAddressLine3(String addressLine3) { this.addressLine3 = addressLine3; }
public String getValidationScore() { return validationScore; }
public void setValidationScore(String validationScore) { this.validationScore = validationScore; }
}
public static class ServicePointRequest {
private String countryCode;
private String postalCode;
private String cityName;
private double longitude;
private double latitude;
private String servicePointResults;
private String language;
// Getters and Setters
public String getCountryCode() { return countryCode; }
public void setCountryCode(String countryCode) { this.countryCode = countryCode; }
public String getPostalCode() { return postalCode; }
public void setPostalCode(String postalCode) { this.postalCode = postalCode; }
public String getCityName() { return cityName; }
public void setCityName(String cityName) { this.cityName = cityName; }
public double getLongitude() { return longitude; }
public void setLongitude(double longitude) { this.longitude = longitude; }
public double getLatitude() { return latitude; }
public void setLatitude(double latitude) { this.latitude = latitude; }
public String getServicePointResults() { return servicePointResults; }
public void setServicePointResults(String servicePointResults) { this.servicePointResults = servicePointResults; }
public String getLanguage() { return language; }
public void setLanguage(String language) { this.language = language; }
}
public static class ServicePointResponse {
private List<ServicePoint> servicePoints;
private int totalCount;
public List<ServicePoint> getServicePoints() { return servicePoints; }
public void setServicePoints(List<ServicePoint> servicePoints) { this.servicePoints = servicePoints; }
public int getTotalCount() { return totalCount; }
public void setTotalCount(int totalCount) { this.totalCount = totalCount; }
}
public static class ServicePoint {
private String id;
private String name;
private String type;
private Address address;
private GeoLocation geoLocation;
private ServicePointDetail servicePointDetail;
// Getters and Setters
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public Address getAddress() { return address; }
public void setAddress(Address address) { this.address = address; }
public GeoLocation getGeoLocation() { return geoLocation; }
public void setGeoLocation(GeoLocation geoLocation) { this.geoLocation = geoLocation; }
public ServicePointDetail getServicePointDetail() { return servicePointDetail; }
public void setServicePointDetail(ServicePointDetail servicePointDetail) { this.servicePointDetail = servicePointDetail; }
}
public static class Address {
private String countryCode;
private String postalCode;
private String addressLocality;
private String streetAddress;
// Getters and Setters
public String getCountryCode() { return countryCode; }
public void setCountryCode(String countryCode) { this.countryCode = countryCode; }
public String getPostalCode() { return postalCode; }
public void setPostalCode(String postalCode) { this.postalCode = postalCode; }
public String getAddressLocality() { return addressLocality; }
public void setAddressLocality(String addressLocality) { this.addressLocality = addressLocality; }
public String getStreetAddress() { return streetAddress; }
public void setStreetAddress(String streetAddress) { this.streetAddress = streetAddress; }
}
public static class GeoLocation {
private double longitude;
private double latitude;
public double getLongitude() { return longitude; }
public void setLongitude(double longitude) { this.longitude = longitude; }
public double getLatitude() { return latitude; }
public void setLatitude(double latitude) { this.latitude = latitude; }
}
public static class ServicePointDetail {
private List<String> services;
private OpeningHours openingHours;
private String contactDetail;
public List<String> getServices() { return services; }
public void setServices(List<String> services) { this.services = services; }
public OpeningHours getOpeningHours() { return openingHours; }
public void setOpeningHours(OpeningHours openingHours) { this.openingHours = openingHours; }
public String getContactDetail() { return contactDetail; }
public void setContactDetail(String contactDetail) { this.contactDetail = contactDetail; }
}
public static class OpeningHours {
private List<OpeningHour> openingHour;
private String holidayDates;
public List<OpeningHour> getOpeningHour() { return openingHour; }
public void setOpeningHour(List<OpeningHour> openingHour) { this.openingHour = openingHour; }
public String getHolidayDates() { return holidayDates; }
public void setHolidayDates(String holidayDates) { this.holidayDates = holidayDates; }
}
public static class OpeningHour {
private String dayOfWeek;
private String openingTime;
private String closingTime;
public String getDayOfWeek() { return dayOfWeek; }
public void setDayOfWeek(String dayOfWeek) { this.dayOfWeek = dayOfWeek; }
public String getOpeningTime() { return openingTime; }
public void setOpeningTime(String openingTime) { this.openingTime = openingTime; }
public String getClosingTime() { return closingTime; }
public void setClosingTime(String closingTime) { this.closingTime = closingTime; }
}
}

Best Practices

  1. Error Handling: Implement comprehensive error handling for DHL API responses
  2. Retry Logic: Add retry mechanisms for transient failures
  3. Rate Limiting: Respect DHL API rate limits and implement backoff strategies
  4. Logging: Log all API requests and responses for debugging
  5. Security: Secure API credentials and use environment variables
  6. Validation: Validate all request parameters before sending to DHL
  7. Caching: Cache frequently accessed data like service points
  8. Monitoring: Monitor API usage and implement alerting for failures

This comprehensive DHL Express API integration provides a solid foundation for shipping, tracking, and logistics operations in Java applications, covering all major DHL services with proper error handling and best practices.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper