Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

чИСТИЛИЩЕ по имени JSMPP

Anna | 3.06.2014 | нет комментариев
Видимо в жизни всякого программиста наступает момент, когда ему становится нужно обучиться отправлятьСМС-сообщения. Вчера такой момент наступил и у меня. Сразу скажу, что эта надобность никак не связана с рекламными рассылками и прочим спамом. СМС-ки потребовалось рассылать в сугубо миролюбивых целях, в рамках реакции на события, найденные в процессе мониторинга оборудования.

Значимость наличия вероятности такой рассылки трудно переоценить. Подлинно, отослав уведомление об аварии на EMail контактного лица, мы не можем рассчитывать на незамедлительное реагирование. Неведомо, когда адресат прочитает свою почту. СМС доставляется гораздо оперативнее.

В нашей компании давным-давно и удачно применяется собственная реализация SMPP-обслуживания и мысль об применении готового SMPP-заказчика на Java показалась мне логичной. Бесстрашно вбив в строку поискаgoogle слова «java smpp client», я незамедлительно обнаружил необходимую мне библиотеку. О том, что происходило дальше, рассказывает мой сегодняшний пост.

От того что для сборки планов я использую maven, первым делом, я скачал с сайта последнюю версиюбиблиотеки, загрузил ее в локальный репозиторий дальнейшей командой:

mvn install:install-file -Dfile=jsmpp-2.1.0.jar -DgroupId=org.jsmpp -DartifactId=smpp -Dversion=2.1.0 -Dpackaging=jar

позже чего сотворил pom-файл:

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.acme.ae.tests.smpp</groupId>
	<artifactId>SMPPTest</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>
	<name>smppTest-${project.version}</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<resource_dir>${project.basedir}/src/main/resources</resource_dir>
	</properties>

	<build>
		<finalName>${project.name}-${project.version}</finalName>
		<resources>
			<resource>
				<directory>${resource_dir}</directory>
			</resource>
		</resources>
	</build>

	<dependencies>
		<dependency>
			<groupId>org.jsmpp</groupId>
			<artifactId>smpp</artifactId>
			<version>2.1.0</version>
		</dependency>
	</dependencies>
</project>

Заготовка тестового приложения выглядела абсолютно стандартно:

Test.java

package com.acme.ae.tests.smpp;

public class Test {

	private void start() throws IOException {
	}

	private void stop() throws IOException {
	}

	private void test()  {
	}

	public static void main(String[] args) {
		Test t = new Test();
		try {
			try {
				t.start();
				t.test();
			} finally {
				t.stop();
			}
		} catch (Exception e) {
			System.out.println(e.toString());
		}
	}
}

Дальше последовало постижение примера, вежливо предоставленного разработчиками. В качестве второго источника вдохновения применялась переводная спецификация.

Для соединения с сервером, в полном соответствии с упомянутым выше примером, применялся дальнейший код:

Соединение с сервером

	...
	private SMPPSession session = null;

	private void start() throws IOException {
		session = new SMPPSession();
		session.connectAndBind(SMPP_IP, SMPP_PORT, 
				new BindParameter(
						BindType.BIND_TX, 
						SMPP_LOGIN, 
						SMPP_PASS, 
						"cp", 
						TypeOfNumber.UNKNOWN, 
						NumberingPlanIndicator.UNKNOWN, 
						null));
	}

	private void stop() throws IOException {
		if (session != null) {
			session.unbindAndClose();
		}
	}
	...

Предназначение части параметров тут абсолютно ясно из контекста. Остальные параметры были взяты из кода примера без изменений. От того что мы собираемся только передавать сообщения, используем BindType.BIND_TX.

Код передачи сообщения (правильней задания кодировки), взятый из примера, компилироваться отказался:

...
new GeneralDataCoding(Alphabet.ALPHA_DEFAULT, MessageClass.CLASS1, false)
...

Позже сопоставления исходников скачанной библиотеки (последней доступной версии 2.1.0) с исходниками наGitHub, выяснилось, что разработчики, по малопонятной мне причине, изменили сигнатуру конструктора:

-    public GeneralDataCoding(boolean compressed, boolean containMessageClass,
-            MessageClass messageClass, Alphabet alphabet) {
     public GeneralDataCoding(Alphabet alphabet, MessageClass messageClass,
             boolean compressed) throws IllegalArgumentException {
            ...
    }

От того что мною применялся ветхий вариант, в код пришлось внести коррективы (адреса отправителя и получателя в коде изменены):

Передача короткого сообщения

	...
	private static TimeFormatter timeFormatter = new AbsoluteTimeFormatter();	

	private void test() throws PDUException, ResponseTimeoutException, InvalidResponseException, NegativeResponseException, IOException {
		String messageId = session.submitShortMessage(
				"CMT", 
				TypeOfNumber.ALPHANUMERIC, 
				NumberingPlanIndicator.UNKNOWN, 
				"ACME", 
				TypeOfNumber.INTERNATIONAL, 
				NumberingPlanIndicator.ISDN, 
				"7XXXXXXXXXX", 
				new ESMClass(), 
				(byte)0, 
				(byte)1,  
				timeFormatter.format(new Date()), 
				null, 
				new RegisteredDelivery(SMSCDeliveryReceipt.DEFAULT), 
				(byte)0,
				new GeneralDataCoding(
						false,
						false,
						MessageClass.CLASS1, 
						Alphabet.ALPHA_DEFAULT),
				(byte)0, 
				"jSMPP simplify SMPP on Java platform".getBytes());

		System.out.println("Message submitted, message_id is "   messageId);
	}
	...

Запуск кода на выполнение не увенчался триумфом. При попытке создания SMPPSession, выбрасывалось исключение:

Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
	at org.jsmpp.session.AbstractSession.<clinit>(AbstractSession.java:51)
	at com.amfitel.m2000.ae.tests.smpp.Test.start(Test.java:56)
	at com.amfitel.m2000.ae.tests.smpp.Test.main(Test.java:179)
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
	at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
	... 3 more

Подлинно, в GettingStarted нашлось скупое припоминание об применении SLF4J. С учетом применения log4j в остальных частях моего плана, это оказалось неприятным сюрпризом.

Но нужно, значит нужно. Пришлось добавить связанность в pom.xml:

		...
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.6.1</version>
		</dependency>
		...

Номер версии (1.6.1, а не 1.4.3, как было сказано в GettingStarted) был взят из pom-файла на GitHub. Сейчас в лог стала писаться неприятная оплошность, но, по крайней мере, соединение с сервером устанавливалось:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Отправка сообщения также выполнялась удачно, но на телефон, взамен букв, приходили «квадратики». На поддержка пришел WireShark:

image

Наш разработчик SMPP-сервера, утверждал, что, для типичной отправки сообщений на латинице, в Data Coding должен отсылаться 0. Нужно сказать, что процесс образования разных числовых кодов, диктуемых спецификацией, при применении JSMPP API не явствен. Позже непродолжительной медитации на начальный код, задача была решена:

				...
				new GeneralDataCoding(
						false,
						false,
-						MessageClass.CLASS1, 
 						MessageClass.CLASS0, 
						Alphabet.ALPHA_DEFAULT)
				...

Сейчас оставалось обучиться отправлять длинные сообщения и сообщения с применением кириллицы. Для отправки длинных сообщений, я не стал мудрить с MESSAGE_PAYLOAD, использовав подход, предлагаемый впримере от разработчиков.

Для передачи кириллицы, требовалось сменить кодировку и перевести сообщение в UCS-2. С утилитарной точки зрения, последнее выливалось в представление текста в виде последовательности байт в кодировке UTF-16 (про разницу между UCS-2 и UTF-16 дозволено прочитать тут). В итоге, код отправки сообщений выглядел дальнейшим образом:

Передача длинного кириллического сообщения

GeneralDataCoding coding = new GeneralDataCoding(
	false,
	false,
	MessageClass.CLASS0, 
	Alphabet.ALPHA_UCS2);

final int totalSegments = 3;
Random random = new Random();
OptionalParameter sarMsgRefNum = OptionalParameters.newSarMsgRefNum((short)random.nextInt());
OptionalParameter sarTotalSegments = OptionalParameters.newSarTotalSegments(totalSegments);

for (int i = 0; i < totalSegments; i  ) {
	final int seqNum = i   1;
	String message = "Сообщение "   seqNum   " of "   totalSegments   " ";
	OptionalParameter sarSegmentSeqnum = OptionalParameters.newSarSegmentSeqnum(seqNum);
	String messageId = session.submitShortMessage(
		"CMT", 
		TypeOfNumber.ALPHANUMERIC, 
		NumberingPlanIndicator.UNKNOWN, 
		"ACME", 
		TypeOfNumber.INTERNATIONAL, 
		NumberingPlanIndicator.ISDN, 
		"7XXXXXXXXXX", 
		new ESMClass(), 
		SMPP_PROTOCOL_ID,   // (byte)0
		SMPP_PRIORITY_FLAG, // (byte)1
		null, 
		null, 
		new RegisteredDelivery(SMSCDeliveryReceipt.DEFAULT), 
		SMPP_REP_IF_P_FLAG, // (byte)0
		coding, 
		(byte)0, 
		message.getBytes(Charset.forName("UTF-16")),
		sarMsgRefNum, 
		sarSegmentSeqnum, 
		sarTotalSegments);

	System.out.println("Message submitted, message_id is "   messageId);
}

Завершая эту статью, хочу подчеркнуть, что она писалась не с целью критики JSMPP. Спецификация SMPP трудна сама по себе, а разработчики библиотеки сделали все допустимое Дабы максимально облегчить процесс ее применения. Мелкие огрехи, в сходственном плане, неминуемы.

Я писал данный пост не с целью кого-нибудь поругать, а лишь из мечты облегчить иным людям хождение по тем граблям, по которым прошел сам. Умоляю не воспринимать мое брюзжание излишне серьезно.

 Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB