How to Send SMS through the SMPP API using Java

The Short Message Peer-to-Peer (SMPP) API is a powerful telecommunications protocol designed for exchanging SMS messages between Short Message Service Centers (SMSCs) and External Short Messaging Entities (ESMEs). By leveraging Java and the SMPP API, developers can build robust applications to send and receive SMS messages efficiently. This comprehensive guide walks you through the process of implementing the SMPP API in Java to connect with the Ozeki SMS Gateway, complete with practical code examples for connection management, message sending, and delivery report handling.

Why Use Java and SMPP API for SMS Messaging?

Java is a versatile, platform-independent programming language widely used for building enterprise-grade applications. When paired with the SMPP API, Java enables developers to create scalable SMS solutions that integrate seamlessly with SMS gateways like Ozeki. The SMPP protocol is ideal for high-throughput SMS applications due to its reliability, support for bulk messaging, and delivery tracking capabilities. This guide uses the jSMPP library, a pure Java implementation of the SMPP protocol, to simplify development.

Java SMPP API Client Setup for Sending SMS Messages

To start sending SMS messages using the SMPP API in Java, you need to set up an SMPP user account on the Ozeki SMS Gateway's SMPP server and configure your Java application to connect to its SMPP server. The jSMPP library is a popular choice for Java developers due to its comprehensive support for SMPP protocol features. Below, we outline the steps to set up your Java project.

Step 1: Add jSMPP Dependency

To use the jSMPP library in your Java project, include the following Maven dependency in your pom.xml file:

<dependency>
    <groupId>org.jsmpp</groupId>
    <artifactId>jsmpp</artifactId>
    <version>2.3.10</version>
</dependency>

This dependency provides all the necessary classes to implement the SMPP API in Java, including session management, message encoding, and delivery receipt handling.

Step 2: Basic SMPP Connection Example

Connecting to an SMPP server requires establishing a session and binding it to the Ozeki SMS Gateway. The following Java code demonstrates how to create a simple SMPP client using the jSMPP library:

import org.jsmpp.*;
import org.jsmpp.bean.*;
import org.jsmpp.session.*;

public class SimpleSMPPClient {
    public static void main(String[] args) {
        SMPPSession session = new SMPPSession();
        try {
            // Connect and bind to the Ozeki SMS Gateway
            session.connectAndBind(
                "your.ozeki.server", 
                2775, 
                new BindParameter(
                    BindType.BIND_TX, 
                    "your_username", 
                    "your_password", 
                    "cp", 
                    TypeOfNumber.ALPHANUMERIC, 
                    NumberingPlanIndicator.UNKNOWN, 
                    null)
            );
            
            System.out.println("Successfully connected to the SMPP server");
            
            // Add message sending code here
            
        } catch (Exception e) {
            System.err.println("Failed to connect and bind to SMPP server: " + e.getMessage());
        } finally {
            session.unbindAndClose();
        }
    }
}

In this example, replace your.ozeki.server, your_username, and your_password with the actual credentials provided by your Ozeki SMS Gateway administrator. The BindType.BIND_TX indicates a transmitter binding, suitable for sending SMS messages.

Managing SMPP API Connections in Java for Reliable SMS Delivery

Reliable SMS delivery requires maintaining an active SMPP connection. The SMPP protocol uses keep-alive messages (enquire_link PDUs) to ensure the connection remains active. Below is an example of how to configure keep-alive settings and monitor session state changes in Java:

session.setEnquireLinkTimer(30000); // Send keep-alive every 30 seconds
session.setTransactionTimer(10000); // Set transaction timeout to 10 seconds

// Add session state listener for monitoring
session.addSessionStateListener(new SessionStateListener() {
    @Override
    public void onStateChange(SessionState newState, SessionState oldState, Session source) {
        System.out.println("SMPP session state changed from " + oldState + " to " + newState);
    }
});

These settings ensure the connection remains stable, and the session state listener helps you monitor changes, such as disconnections, for robust error handling.

Sending SMS with Java through the SMPP API

Once connected, you can send SMS messages using the submit_sm PDU. The following Java method demonstrates how to send an SMS using the SMPP API in Java:

public static void sendSMS(SMPPSession session, String sender, String recipient, String message) throws Exception {
    try {
        String messageId = session.submitShortMessage(
            "CMT", // Service type
            TypeOfNumber.ALPHANUMERIC, // Source TON
            NumberingPlanIndicator.UNKNOWN, // Source NPI
            sender, // Sender address
            TypeOfNumber.INTERNATIONAL, // Destination TON
            NumberingPlanIndicator.ISDN, // Destination NPI
            recipient, // Recipient address
            new ESMClass(), // ESM class
            (byte)0, // Protocol ID
            (byte)1, // Priority flag
            null, // Schedule delivery time
            null, // Validity period
            new RegisteredDelivery(SMSCDeliveryReceipt.SUCCESS_FAILURE), // Delivery receipt
            (byte)0, // Replace if present flag
            new GeneralDataCoding(Alphabet.ALPHA_DEFAULT), // Data coding
            (byte)0, // Default message ID
            message.getBytes() // Message content
        );
        
        System.out.println("SMS submitted with message ID: " + messageId);
    } catch (PDUException e) {
        System.err.println("Invalid PDU parameter: " + e.getMessage());
        throw e;
    } catch (ResponseTimeoutException e) {
        System.err.println("Response timeout: " + e.getMessage());
        throw e;
    } catch (InvalidResponseException e) {
        System.err.println("Invalid response: " + e.getMessage());
        throw e;
    } catch (NegativeResponseException e) {
        System.err.println("Received negative response: " + e.getMessage());
        throw e;
    } catch (Exception e) {
        System.err.println("Failed to send SMS: " + e.getMessage());
        throw e;
    }
}

This method sends an SMS with delivery receipt tracking enabled. The RegisteredDelivery parameter ensures you receive notifications about the message's delivery status.

Handling SMS Delivery Reports with Java and the SMPP API

To track whether an SMS was successfully delivered, you can bind your SMPP session as a transceiver (BindType.BIND_TRX) and implement a message receiver listener. Below is an example of how to handle delivery reports in Java:

// Bind as transceiver to send and receive messages
BindParameter bindParam = new BindParameter(
    BindType.BIND_TRX,
    "your_username",
    "your_password",
    "cp",
    TypeOfNumber.ALPHANUMERIC,
    NumberingPlanIndicator.UNKNOWN,
    null
);

// Set message receiver listener for delivery reports
session.setMessageReceiverListener(new MessageReceiverListener() {
    @Override
    public void onAcceptDeliverSm(DeliverSm deliverSm) {
        if (MessageType.SMSC_DEL_RECEIPT.containedIn(deliverSm.getEsmClass())) {
            DeliveryReceipt delReceipt = deliverSm.getShortMessageAsDeliveryReceipt();
            System.out.println(String.format(
                "Received delivery receipt for message %s: %s",
                delReceipt.getId(),
                delReceipt.getFinalStatus()
            ));
        }
        
        // Respond to delivery report
        try {
            byte[] messageId = new byte[]{1};
            session.deliverSmResponse(0, messageId, deliverSm);
        } catch (PDUException e) {
            System.err.println("Failed to respond to deliver_sm: " + e.getMessage());
        }
    }
});

This code processes delivery receipts, allowing you to track the success or failure of each SMS sent through the SMPP API in Java.

Complete Java SMPP Client for SMS Sending via the SMPP API

Below is a complete Java class that integrates connection management, message sending, and delivery report handling. This implementation is production-ready with proper error handling and resource management:

import org.jsmpp.*;
import org.jsmpp.bean.*;
import org.jsmpp.session.*;
import org.jsmpp.util.*;

public class SMPPClient implements AutoCloseable {
    private SMPPSession session;
    private String host;
    private int port;
    private String username;
    private String password;
    
    public SMPPClient(String host, int port, String username, String password) {
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
        this.session = new SMPPSession();
    }
    
    public void connect() throws Exception {
        try {
            BindParameter bindParam = new BindParameter(
                BindType.BIND_TRX,
                username,
                password,
                "cp",
                TypeOfNumber.ALPHANUMERIC,
                NumberingPlanIndicator.UNKNOWN,
                null
            );
            
            session.connectAndBind(host, port, bindParam);
            
            // Configure session settings
            session.setEnquireLinkTimer(30000);
            session.setTransactionTimer(10000);
            
            // Set up delivery receipt handler
            session.setMessageReceiverListener(new DeliveryReceiptListener());
            
            System.out.println("Successfully connected to SMPP server");
        } catch (Exception e) {
            System.err.println("Failed to connect to SMPP server: " + e.getMessage());
            throw e;
        }
    }
    
    public String sendSMS(String sender, String recipient, String message) throws Exception {
        try {
            return session.submitShortMessage(
                "CMT",
                TypeOfNumber.ALPHANUMERIC,
                NumberingPlanIndicator.UNKNOWN,
                sender,
                TypeOfNumber.INTERNATIONAL,
                NumberingPlanIndicator.ISDN,
                recipient,
                new ESMClass(),
                (byte)0,
                (byte)1,
                null,
                null,
                new RegisteredDelivery(SMSCDeliveryReceipt.SUCCESS_FAILURE),
                (byte)0,
                new GeneralDataCoding(Alphabet.ALPHA_DEFAULT),
                (byte)0,
                message.getBytes()
            );
        } catch (Exception e) {
            System.err.println("Failed to send SMS: " + e.getMessage());
            throw e;
        }
    }
    
    @Override
    public void close() {
        if (session != null) {
            session.unbindAndClose();
        }
    }
    
    private static class DeliveryReceiptListener implements MessageReceiverListener {
        @Override
        public void onAcceptDeliverSm(DeliverSm deliverSm) {
            if (MessageType.SMSC_DEL_RECEIPT.containedIn(deliverSm.getEsmClass())) {
                DeliveryReceipt delReceipt = deliverSm.getShortMessageAsDeliveryReceipt();
                System.out.println(String.format(
                    "Received delivery receipt for message %s: %s",
                    delReceipt.getId(),
                    delReceipt.getFinalStatus()
                ));
            }
        }
    }
    
    public static void main(String[] args) {
        try (SMPPClient client = new SMPPClient(
                "your.ozeki.server", 
                2775, 
                "your_username", 
                "your_password")) {
            
            client.connect();
            
            String messageId = client.sendSMS(
                "12345", 
                "+1234567890", 
                "Hello from Java SMPP client!"
            );
            
            System.out.println("SMS sent with ID: " + messageId);
            
            // Keep application running to receive delivery reports
            System.out.println("Press Ctrl+C to exit...");
            Thread.sleep(Long.MAX_VALUE);
            
        } catch (Exception e) {
            System.err.println("Error in SMPP client: " + e.getMessage());
        }
    }
}

This complete implementation encapsulates the SMPP client functionality in a reusable class, making it easier to integrate into larger Java applications. The AutoCloseable interface ensures proper resource cleanup.

Best Practices for Building Java SMPP Clients

To ensure your Java SMPP API client is robust and scalable, follow these best practices:

  • Connection Pooling: Use connection pooling for high-volume SMS applications to manage multiple SMPP sessions efficiently.
  • Exception Handling: Implement comprehensive exception handling to recover from network issues or server errors.
  • Thread Pools: Use thread pools for concurrent message processing to improve performance.
  • Message Queuing: Implement a queuing mechanism to ensure reliable message delivery during network disruptions.
  • Connection Monitoring: Monitor the SMPP session state and implement automatic reconnection logic for reliability.
  • Character Encoding: Handle different character encodings (e.g., GSM 7-bit, UCS-2) to support international SMS messaging.

Conclusion

Implementing the SMPP API in Java with the Ozeki SMS Gateway provides a powerful solution for sending and receiving SMS messages in your applications. The jSMPP library simplifies the complexities of the SMPP protocol, allowing developers to focus on building robust messaging features. This guide has covered the essentials of setting up a Java SMPP client, managing connections, sending SMS messages, and handling delivery reports. By following the provided examples and best practices, you can create scalable and reliable SMS applications using Java and the SMPP API.

For production environments, consider adding advanced features like message concatenation for long SMS, detailed logging, and performance monitoring. The SMPP protocol offers additional capabilities, such as scheduled message delivery and priority settings, to enhance your application as requirements evolve.

More information