Еще несколько подробностей относительно ConcurrentAccessException : согласно спецификации EJB, доступ к SLSB синхронизируется приложением. сервер. Однако это не относится к SFSB. Бремя обеспечения одновременного доступа к SFSB лежит на плечах разработчика приложения.
Почему? Ну, синхронизация SLSB необходима только на уровне экземпляра. То есть каждый конкретный экземпляр SLSB синхронизируется, но у вас может быть несколько экземпляров в пуле или на другом узле в кластере, и одновременные запросы в разных экземплярах не являются проблемой. К сожалению, с SFSB это не так просто из-за пассивации / активации экземпляров и репликации в кластере. Вот почему спецификация не обеспечивает это. Посмотрите это предположение , если вы заинтересованы в теме.
Это означает, что использовать SFSB из сервлета сложно. Пользователь с несколькими окнами из одного сеанса или перезагрузка страницы до завершения рендеринга может привести к одновременному доступу. Каждый доступ к EJB, выполняемый в сервлете, должен быть теоретически синхронизирован на самом бине. Я создал InvocationHandler для синхронизации всех вызовов конкретного экземпляра EJB:
public class SynchronizationHandler implements InvocationHandler {
private Object target; // the EJB
public SynchronizationHandler( Object bean )
{
target = bean;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
synchronized( target )
{
// invoke method to the target EJB
}
}
}
Затем, сразу после получения удаленной ссылки на EJB, вы оборачиваете его SynchronizationHandler
. Таким образом, вы уверены, что этот конкретный экземпляр не будет доступен одновременно из вашего приложения (если он работает только в одной JVM). Вы также можете написать обычный класс-оболочку, который синхронизирует все методы компонента.
Тем не менее мой вывод таков: используйте SLSB, когда это возможно.
EDIT
Этот ответ отражает спецификации EJB 3.0 (раздел 4.3.13):
Клиенты не могут совершать одновременные вызовы в сеанс с состоянием
объект. Если вызываемый клиентом бизнес-метод выполняется в
случай, когда другой вызов, вызванный клиентом, из того же или другого
клиент прибывает в тот же экземпляр класса сессионного компонента с сохранением состояния,
если второй клиент является клиентом бизнес-интерфейса компонента,
одновременный вызов может привести к тому, что второй клиент получит
javax.ejb.ConcurrentAccessException
Такие ограничения были удалены в EJB 3.1 (раздел 4.3.13):
По умолчанию клиентам разрешено совершать одновременные вызовы с сохранением состояния
объект сеанса и контейнер требуются для сериализации таких
одновременные запросы.
[...]
Разработчик бина может по желанию указать этот параллельный клиент
Запросы к сессионному компоненту с состоянием запрещены. Это делается с помощью
дескриптор развертывания аннотации @AccessTimeout или тайм-аута доступа
элемент со значением 0. В этом случае, если клиент вызвал бизнес
метод выполняется в случае, когда другой вызов, вызванный клиентом,
от того же или другого клиента, прибывает в тот же экземпляр
сессионный компонент с сохранением состояния, если второй клиент является клиентом компонента
бизнес-интерфейс или представление без интерфейса, одновременный вызов
должен привести к получению второго клиента
javax.ejb.ConcurrentAccessException