Подтвердить что ты не робот

Thread.sleep() в EJB

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

Каким будет лучший способ реализовать это?

4b9b3361

Ответ 1

В часто задаваемые вопросы по ограничениям EJB в нем указано, что вы

не следует создавать или управлять потоками

И включение потока в сон считается "управлением".

В вашем случае, когда веб-служба возвращает статус "занят", вы можете запланировать задание, чтобы повторить отправку сообщения в более поздний момент времени, например, используя Quartz Scheduler. Выполнение завершится там, и любая дальнейшая обработка должна быть делегирована планировщику заданий.

Ответ 2

EJB 3.1 принес новый @Asynchronous feature, который вы можете использовать:

@Asynchronous
@TransactionAttribute(NOT_SUPPORTED)
public Future<WebServiceResult> callWebService(int retries) {
    WebServiceResult result = webService.call();

    if (!result.equals(BUSY)) {
        return result;
    }

    if (retries <= 0) {
        throw new TooBusyException();
    }

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }

    return callWebService(retries - 1);
}

Затем просто позвоните в веб-службу:

Future<WebServiceResult> result = yourEJB.callWebService(1);

// Can do some interesting stuff here.
// ...
// ...

result.get(2, SECONDS);  // Block for up to 2 seconds.

Как вы можете видеть, вы получаете настраиваемое количество попыток и тайм-аута бесплатно.

Как это отличается от простого вызова Thread.sleep()? Возврат Future более явный и управляемый. Также я не думаю, что Thread.sleep() - это вредно. Единственная проблема заключается в том, что этот экземпляр EJB теперь может использоваться повторно другими клиентами. При асинхронном вызове Future происходит внутри некоторого другого EJB и пула потоков. Что касается важности Thread#interrupt() внутри блока catch, обратитесь к Зачем вызывать Thread.currentThread.interrupt(), когда вы catch any InterruptException?

Другая идея: использовать аспект во время вызова веб-сервиса, ловить BusyException один раз и повторить попытку.

Ответ 3

Но внешний веб-сервис является внешним, и вы открываете ему сетевое соединение, и вы хотите сделать некоторые вещи управления. Для JCA это не EJB.