SMS-Powered Applications
Pages: 1, 2
First we have to instantiate a new Connection object
with the desired host and port parameters.
The third parameter defines the connection as asynchronous and could be left
out if you want to use some other approach.
Next, we should bind the connection with the connection type and
credentials provided by the message center. We will bind as a TRANSCEIVER,
as we want to both submit and receive messages. The parameters that have
to be passed are system identification and a "secret," used for
authentication purposes. Also, you should pass a "system type" parameter
that defines the application's purpose, such as VMS
for a voice mail system. This parameter is not required by
all SMSCs, and its default value is null.
At this point, the underlying network connection will be
established, and if the SMSC is currently down or unreachable,
an IOException will be thrown. There are a few things that
you could do in this case, such as log the error and exit. Our
requirement is to deal with these situations, so we will try to
bind again after a one minute delay.
public void run() {
while (!exit) {
connect();
synchronized(this) {
try {
wait();
} catch (InterruptedException ie) {
}
}
}
}
Our main application thread is quite simple: it binds the connection
and sleeps until the connection terminates or an exit flag is set. In
the first case, we will try to bind again (see the connect method
above). In the latter case, we exit the application due to some
unrecoverable error such as when binding is refused from the SMSC (which
means that the submitted parameters are not correct) -- in this case,
there is no point executing the application until the error is resolved.
This is of course only one possible architectural approach, and
you should adopt this API to your needs and environment.
One more tip that could be used is to create a shutdown hook, which will unbind our application from the SMSC when the application terminates or crashes. That way, we will be sure that we have done everything to write an application that will behave properly under any circumstances. The code below simply unbinds the connection if it exists and is currently bound:
package net.nighttale.smsdemo;
import ie.omk.smpp.Connection;
public class Hook extends Thread {
public void run() {
System.out.println("Unbinding");
Connection conn = SMSDemo.getInstance().getConnection();
if(conn != null && conn.isBound())
conn.force_unbind();
}
}
Adding it to the list of runtime hooks is a simple call:
Runtime.getRuntime().addShutdownHook(new Hook());
One issue with asynchronous communication is how to implement
receiving functionality. The observer pattern is the right solution for these
sort of problems, so the SMPP API provides a ConnectionObserver
interface for this purpose. To be enabled to receive messages (and
other relevant events), our demo class has to implement this
interface, and we have to write code for two methods defined by it.
Next, this observer should be attached to the connection using the
addObserver method, as shown in the in the connect
method above. The first method we will look at is update,
which accepts Connection and SMPPEvent as
arguments.
public void update(Connection conn, SMPPEvent ev) {
if (ev.getType() == SMPPEvent.RECEIVER_EXIT
&& ((ReceiverExitEvent)ev).isException()) {
synchronized(this) {
notify();
}
}
}
There are three types of events generated by the receiver thread. One
caught in the demo is SMPPEvent.RECEIVER_EXIT, which is
generated when receiver thread exits either normally or due to an
exception. In the latter case, the isException() method will
return true, which means that the network connection to the SMSC
is invalid and we should reconnect in order to continue. In
this case, we wake up our main thread and try to make a new
connection. The second event type is SMPPEvent.RECEIVER_EXCEPTION,
which means that receiver has caught an exception that has not caused it
to terminate. It would be useful to log this event, but to keep the example code
simple, this logging has been left out. Finally, there is
SMPPEvent.RECEIVER_START, which is generated when the thread receiver
starts, and can be ignored.
The more important method of the ConnectionObserver
interface is packetReceived:
public void packetReceived(Connection conn,
SMPPPacket pack) {
switch(pack.getCommandId()) {
case SMPPPacket.DELIVER_SM :
try {
SubmitSM response = processRequest(pack);
SubmitSMResp smr =
(SubmitSMResp)conn.sendRequest(response);
} catch (Exception e) {
e.printStackTrace();
}
break;
case SMPPPacket.BIND_TRANSCEIVER_RESP :
if (pack.getCommandStatus() != 0) {
System.out.println("Error binding: " +
pack.getCommandStatus());
exit = true;
synchronized(this) {
notify();
}
} else {
System.out.println("Bounded");
}
}
}
This is the point where all the PDUs sent from the SMSC are collected in
the application. In this demo, we will collect only two types:
SMPPPacket.DELIVER_SM (a SMS submitted
by the customer) and SMPPPacket.BIND_TRANSCEIVER_RESP
(a response PDU from the SMSC to our bind request). For the binding
response, if we detect that we haven't successfully bound to the SMSC,
we set the exit flag, which will terminate the
application.
Before we proceed to the SMS processing, it should be noted that
implementing the "raw" ConnectionObserver
interface leads to clumsy code, because you will have a long, ugly
switch-case structure in these two methods. I used it in this demo
for demonstration purposes, and I didn't handle all that has to be
handled for a production application. So, if you will be coding an
application that will handle (nearly) all possible cases, you should
consider using the ie.omk.smpp.event.SMPPEventAdapter class, which
implements this interface and has predefined methods for all packets
and events that could be handled. You can learn more about this class
by reading the SMPP API's Javadoc.
OK, now let's get back to our demo. All SMS messages delivered
from the SMSC are handled by the processRequest method.
private SubmitSM processRequest(SMPPPacket request)
throws BadCommandIDException {
SubmitSM sm =
(SubmitSM)conn.newInstance(SMPPPacket.SUBMIT_SM);
sm.setDestination(request.getSource());
String[] parts = request.getMessageText().split(" ");
logPacket(request, "IN");
if (parts[0].equalsIgnoreCase("balance")) {
User user =
User.findByPhone(request.getSource().getAddress());
if (user == null)
sm.setMessageText("Your phone number is not " +
"registered in our database! " +
"Please contact one of our offices");
else if (!user.getAccountNumber().equalsIgnoreCase(parts[1]))
sm.setMessageText("Account number that you " +
"have entered is not correct! " +
"Please try again");
else
sm.setMessageText("Balance on your account is "
+ user.getBalance() + "$");
} else {
sm.setMessageText("Wrong message format! " +
"Please send BALANCE " +
"<ACCOUNT_NUMBER>");
}
logPacket(sm, "OUT");
return sm;
}
Here, we will create a response message that will be delivered to the user
by calling the newInstance method of the Connection
class with the appropriate PDU type (SUBMIT_SM in this
case). Next, we should specify the phone number of the user by
setting the destination field of the packet (setDestination),
which, in the case of a simple reply, is exactly the same as the source of
the received message. Now, we parse the text of the message to
get all of the necessary data to process the input. Thus far, we have
been discussing and coding communication, but this is the entry
point to the business logic of the application. For this simple demo,
I have implemented a mock-up User class to represent the
business logic.
package net.nighttale.smsdemo;
public class User {
private String phoneNumber;
private String accountNumber;
private float balance;
public User (String phoneNumber,
String accountNumber,
int balance) {
this.phoneNumber = phoneNumber;
this.accountNumber = accountNumber;
this.balance = balance;
}
public static User findByPhone(String phoneNumber) {
if (phoneNumber.equals("063123456"))
return new User(phoneNumber, "123456", 10000);
else
return null;
}
public String getAccountNumber() {
return accountNumber;
}
public float getBalance() {
return balance;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
public void setBalance(float balance) {
this.balance = balance;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
The class has one finder method (findByPhone), a
constructor, and getter/setter methods. For simplicity, findByPhone
returns a valid user only for one phone number and null
in all other cases. Of course, this should be replaced with a real
class implemented in any convenient technology, such as EJBs, that
would search and retrieve data from the database.
Depending on the message format, the user's telephone number, and (if the
message was well-formatted) the submitted account number, some appropriate text is set
as the return message to the user, using the setMessageText method.
At the end, the message is submitted to the SMSC
using the sendRequest method of the Connection
class and passing the previously formed PDU as a parameter to it.
Simulator
When you are developing a SMPP-based application, you will probably want to set up a local environment for development and initial testing purposes. This is often useful because the process of obtaining access to an operator's SMSC could be time-consuming, and providers usually run detailed acceptance tests before letting your application access their SMSC. For all of these reasons, it is convenient to install some kind of SMSC simulator in your development environment. In this article, we will briefly describe SMPPSim, an open source Java SMSC simulator, and test our demo application with it.
After downloading and extracting the archive, you are ready to run the simulator by simply typing
startsmppsim
on a Windows platform, or
./startsmppsim
on Unix-like systems, in the root directory of the extracted simulator.
By default, the SMPPSim will open a network connection on port 2775 and wait to be bound by our application.
Configuration of SMPPSim is done through one of the props
files in the conf directory. Depending on the underlying
operating system, you should use the props.unix or props.win
file. We will not dig deeper into setting details, and instead just use it to
turn on message delivery from the SMSC to our application. To do that,
you should change settings in the # DELIVERY SERVICE
section. You should set the number of messages that message center will
send to our application per minute with the parameter
DELIVERY_MESSAGES_PER_MINUTE and the file that contains
messages that will be randomly sent (DELIVER_MESSAGES_FILE).
The default message delivery file is deliver_messages.csv,
which can be found in the root folder of SMPPSim. Now let's make a
few test cases for the demo.
063123456,1000,A test message
063123456,1000,BALANCE 123456
063123456,1000,balance 123456
063123456,1000,balance 123457
063123457,1000,balance 123456
In the delivery file, each line represents one SMS message to be
delivered to the application. You should specify the user's phone number,
ESME system identification, and text message, in a comma-separated
fashion. Messages will be delivered to the application in random
order at the rate defined in the configuration file. Recall
that the findByPhone method of the User stub class
will return a valid user only if the specified number is 063123456. The
appropriate account number for that phone number is 123456. So this
delivery file should generate all possible test cases. Set the number
of messages to be delivered per minute (for example, 10), copy the
delivery file (or generate one of your own) from the demo folder to
SMPPSim folder, run SMPPSim, run the demo application, and watch how they
communicate. You should get something like this on your console
window.
2004-04-04 02:51:41,585 DEBUG [Thread-1] ie.omk.smpp.util
Loaded API properties from /smppapi.properties
2004-04-04 02:51:41,585 DEBUG [Thread-1] ie.omk.smpp.util
-- listing properties --
smppapi.net.tcp.so_timeout=300000
smppapi.net.autoflush=true
smppapi.connection.rcv_daemon.ioex_count=3
Bounded
IN: 063123456 - BALANCE 123456
OUT: 063123456 - Balance on your account is 10000.0$
IN: 063123456 - balance 123457
OUT: 063123456 - Account number that you have entered is not
correct! Please try again
IN: 063123456 - balance 123456
OUT: 063123456 - Balance on your account is 10000.0$
IN: 063123456 - BALANCE 123456
OUT: 063123456 - Balance on your account is 10000.0$
IN: 063123456 - A test message
OUT: 063123456 - Wrong message format! Please send BALANCE
<ACCOUNT_NUMBER>
IN: 063123456 - balance 123456
OUT: 063123456 - Balance on your account is 10000.0$
IN: 063123457 - balance 123456
OUT: 063123457 - Your phone number is not registered in our
database! Please contact one of our offices
IN: 063123456 - balance 123456
OUT: 063123456 - Balance on your account is 10000.0$
IN: 063123456 - balance 123457
OUT: 063123456 - Account number that you have entered is not
correct! Please try again
IN: 063123457 - balance 123456
OUT: 063123457 - Your phone number is not registered in our
database! Please contact one of our offices
IN: 063123456 - BALANCE 123456
OUT: 063123456 - Balance on your account is 10000.0$
IN: 063123456 - balance 123457
OUT: 063123456 - Account number that you have entered is not
correct! Please try again
Now you can try to start and stop the simulator (to simulate network problems) and see how the application reacts.
Further Research
We've scratched the surface of the SMPP protocol and some ways you can use it on your project. There are many details that were left out, but I hope that you are at least a little curious and that you will dig deeper into this topic. To do that, you should follow one of the related links. SMS messages are definitely a powerful way to provide instant message delivery to a large audience. We mentioned just a few possible usages here, but I'm sure that more and more applications will be opened through this interface to their users.
However before starting to code your SMPP solution, check some of the existing gateway projects and products (such as Kannel). It may save you time if your requirements are not complex, and you certainly don't want to reinvent the wheel and make your own gateway if you don't need to.
Related Links
- SMSDemo.zip: sample code for this article
- SMPP Forum: SMPP specification, forum, links, tools
- SMPP API: Open source SMPP library for Java
- SMPPSim: Open source SMSC simulator
- Kannel: Open source WAP and SMS gateway
- SMS Tools: SMS-related tools, including another Java API
Dejan Bosanac is a software developer, technology consultant and author. He is focused on the integration and interoperability of different technologies, especially the ones related to Java and the Web.
Return to ONJava.com.
-
to get out of wait() method
2010-04-19 00:16:28 test.123456 [View]
-
SMSDemo binding error
2009-11-16 22:40:40 macksm63 [View]
-
running the smsdemo sample app
2009-09-10 23:19:03 frusher [View]
-
running the smsdemo sample app
2009-09-10 23:06:09 frusher [View]
-
SMSC is not getting a delivery report
2009-07-20 08:51:51 Sudipto10 [View]
-
Reply to be sent to
2009-05-25 22:15:34 ancy joseph [View]
-
Compilation Error Please Help
2009-05-25 22:10:43 ancy joseph [View]
-
Got Error while compiling
2009-05-25 22:00:20 ancy joseph [View]
-
Program runs bit canr bind with smsc !
2009-03-24 04:10:50 CharuJoshi [View]
-
SMPPSim has moved!
2009-01-13 03:06:30 mdwoolley [View]
-
Help with SMS and Simulator
2008-10-27 06:33:35 vKartik [View]
-
About smsDemo application
2008-07-14 03:27:48 riteshsc [View]
-
About smsDemo
2008-07-01 05:22:21 MukeshB [View]
-
Please help me...
2008-04-25 07:11:43 yshashidhar [View]
-
I need complete details about SMPP
2007-11-29 22:40:25 SMPPprotocaid [View]
-
I need complete details about SMPP
2007-11-29 22:41:49 SMPPprotocaid [View]
-
I need complete details about SMPP
2008-04-24 10:06:13 kimwatu [View]
-
Regarding SMSC
2007-04-25 05:38:19 somsuresh [View]
-
help
2006-10-15 02:58:32 nazari [View]
-
How can i send MMS from pc to handphone?
2006-09-27 23:42:47 Apit [View]
-
How can i send MMS from pc to handphone?
2006-09-27 23:42:41 Apit [View]
-
Please help me
2006-08-02 00:29:53 prabhatidubey [View]
-
how to hire SMSC service
2006-05-03 05:32:00 VikramRawal [View]
-
Change the smsc configuration
2006-04-19 03:26:16 theDistiller [View]
-
smsc
2006-04-01 22:35:12 iamlateef [View]
-
SMPP accounts are usually expensive
2006-02-04 10:01:50 marre99 [View]
-
I need your help
2005-05-20 16:51:10 SureshR [View]