2011-09-28 1 views
1

Я занимаюсь созданием веб-службы, которая будет получать запросы на отправку сообщений через XMPP. Однако все сообщения будут отправляться с одной учетной записи (сервер регистрируется и отправляет уведомления пользователям).Как обеспечить создание только одного XMPPConnection? Использовать синглтоны?

В этом заключается проблема - как ее реализовать? Я пытался реализовать класс XMPPConnection как синглтон, но я застрял в передаче аргументов конструкторам, содержащих имя хоста, порт, JID и т.д.

Как я уже читал here, одноэлементно с параметрами не одноэлементно ... Таким образом, я думал о решении его следующим образом (это какой-то завод?):

public class XMPPConnectionSingleton 
{ 
    private volatile static XMPPConnectionSingleton anInstance; 
    private volatile static XMPPConnection connection; 

    public static XMPPConnectionSingleton getInstance() { 
     if(anInstance == null) { 
      synchronized (XMPPConnectionSingleton.class) { 
       if(anInstance == null) 
        anInstance = new XMPPConnectionSingleton(); 
      } 
     } 
     return anInstance; 
    } 

    public void init(String server, int port, String jid, String password, String resource) 
    { 
     ConnectionConfiguration conf = new ConnectionConfiguration(server, port); 
     connection = new XMPPConnection(conf); 
     // logging in, etc. 
    } 
} 

это хороший способ пойти? Или, может быть, лучше сделать класс упаковки для XMPPConnection, приняв конструктор без параметров?

+0

Ключевой вопрос заключается в том, как ваш веб-сервис будет работать, вы ожидаете одновременного вызова? И если это так, разрешает ли сервер XMPP одновременное подключение нескольких подключенных клиентов? – ThomasRS

+0

Одновременные вызовы могут возникать, так как веб-служба будет использоваться в средах разных размеров. Что вы подразумеваете под несколькими подключенными клиентами одновременно? Сервер XMPP должен принимать только одно соединение с WS-сервера. –

+0

Да, в соответствии с другими вопросами [здесь] (http://stackoverflow.com/search?q=XMPP+multiple+clients+), может показаться, что одновременно возможно несколько клиентов. Если не слишком много накладных расходов, вы можете подумать об этом. – ThomasRS

ответ

0

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

Ужасный, простой подход - синхронизация в одном экземпляре, и все вызовы WS ждут. Это будет отлично работать для низкой емкости. Использование ReentrantLock может несколько усилить эту логику - например, отправив ответ WS-ответа, а не весь HTTP-вызов.

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

В зависимости от логики в ваших вызовах WS (требуется ли подтверждение того, что сообщение отправлено в XMPP?), Вы можете подумать о очередности вызовов и обслуживании их из другого потока, возвращая WS-вызов до отправки фактического сообщения (Время удержания http обычно 30 секунд, но может быть изменено).

Возможно даже, чтобы каждый сеанс WS подключался и имел свой сеанс в течение всего времени вызова.

Edit: Я предлагаю вам идти с

// Correct lazy initialization in Java 
@ThreadSafe 
class Foo { 
    private static class HelperHolder { 
     public static Helper helper = new Helper(); 
    } 

    public static Helper getHelper() { 
     return HelperHolder.helper; 
    } 
} 

где помощник

  1. вспомогательный класс, который вытащить данные входа где-то, обертывания класс клиента XMPP или
  2. сам клиентский класс XMPP с жестко запрограммированной информацией для входа в систему.

Затем просто используйте синхронизированный оператор на возвращаемом объекте.

+0

К сожалению, я не понимаю, как вы хотите использовать синхронизацию. Не могли бы вы прояснить это немного? Основная проблема, с которой я сталкиваюсь, заключается не в том, как создать одноэлемент, а в том, как создать псевдо-синглтон, который может быть построен с параметрами. Или, альтернативно, какое решение можно использовать для передачи одного экземпляра объекта XMPPConnection между всеми вызовами WS. Если вы говорите о многих параллельных сеансах - я хочу создать 1 объект соединения, который будет использоваться для всех запросов WS для отправки сообщений. WS должен вернуть клиенту «успех»/«не удалось». –

+0

См. Редактирование. Вы говорите, что сам клиент XMPP является потокобезопасным? – ThomasRS

+0

1) Теперь у меня возникла ваша идея, но как бы вы потянули информацию о входе в класс упаковки? Единственный способ, по которому я вижу, это init() после построения и после проверки, если не инициализирован. Мне кажется очень похожим на мое решение вопроса, не так ли? Я новичок, возможно, есть некоторые существенные отличия, которые я просто не замечаю :) 2) Ну, я не думал о том, что клиент XMPP является потокобезопасным, но кажется, что [это] (http://community.igniterealtime.org/thread/19605). –

0

Это звучит для меня как неправильный подход. Почему бы просто не запросить WS-запросы в очереди и попросить один поток прочитать запросы и написать сообщения через xmpp. Будет только одно соединение, но нет необходимости создавать какой-либо пользовательский код для создания одноэлементного соединения вообще.

+0

Мне нужна обратная связь, если отправка сообщения прошла успешно, помещение всего в очередь делает это невозможным. К сожалению. –

+0

Нет, вам просто нужно использовать какой-то механизм, который блокирует и возвращает результат, например, FutureTask. Главное - просто обмениваться одним соединением. – Robin