Согласно спецификации, опция (b) является правильным поведением.Если вы получаете опцию (а) и полагаетесь на нее, приложение не будет переносимым.
В приведенном ниже объяснении я имею в виду конкретно спецификацию JMS Версия 1.1 12 апреля 2002 года .
Существует некоторая путаница, вызванная тем, что метод подтверждения вызывается из объекта сообщения, когда фактически он работает на уровне сеанса.Поскольку это метод сообщения, интуитивно кажется правильным, что можно было бы выбрать точку в потоке сообщений для генерирования подтверждения.
Что действительно происходит, хотя это то, что подтверждение сообщения управляет вызовами фиксации в сеансеуровень.Поскольку сеанс может иметь только одну активную транзакцию за раз, каждое подтверждение ограничивает не точку в потоке сообщений, а точку во времени .Ack фиксирует существующую единицу работы и запускает следующую.Сообщения, доставленные до подтверждения , должны быть включены в единицу работы, подтвержденную подтверждением .
Термин «доставлено» обычно считается завершением вызова API, удаляющегосообщение из очереди и приводит к заполнению объекта в памяти программы.В действительности, сообщение считается доставленным, когда оно удаляется из очереди, независимо от того, попадает ли оно в программу.Например, рассмотрим следующую последовательность событий:
- Приложение запрашивает сообщение.
- Запрос передается через сокет TCP процессу на сервере, который действует как проксидля приложения.
- Прокси-сервер выдает GET для очереди.
- Сообщение заблокировано в единице работы и передано процессу прокси.
- Процесс проксипытается доставить сообщение через сокет TCP вызывающему приложению.Если в этот момент соединение разорвано, приложение никогда не увидит сообщение, но провайдер JMS считает, что оно доставлено.При обнаружении разорванного соединения единица работы отменяется, сообщение откатывается в очередь и счетчик повторных поставок увеличивается.
- Приложение получает сообщение.
- Приложение подтверждаетсообщение.
- Процесс прокси получает вызов коммита и выполняет его.
Между 6 и 8 имеется окно, в течение которого сокет TCP может быть отключен.Со стороны провайдера JMS, он не может действительно отличить это от сбоя на шаге 5. В любом случае, сообщение откатывается и доставляется позже.Однако в этом случае приложение увидит сообщение дважды.Спецификация ожидает эту ситуацию в 4.4.13, где говорится:
Если сбой происходит между моментом, когда клиент фиксирует свою работу над сеансом, и методом фиксации возвращается, клиент не может определить, была ли транзакциябыло совершено или отменено.Та же самая неоднозначность существует, когда происходит сбой между нетранзакционной отправкой сообщения PERSISTENT и возвратом из метода отправки.
Это дело JMS-приложения, чтобы справиться с этой неоднозначностью.В некоторых случаях это может привести к тому, что клиент будет создавать функционально дублирующиеся сообщения.
Сообщение, которое доставляется в результате восстановления сеанса, не считается дублирующим сообщением.
В вашем примере, гдевы «вызываете customer.receive () 6 раз, а затем вызываете .acknowledge для 3-го сообщения» и наблюдаете, что сообщения с 4 по 6 доставляются, возможные объяснения состоят в том, что а) шесть сообщений не все из одного сеанса,или б) поведение не соответствует спецификации.