Выяснение того, какой вид EJB использовался

Предположим, у меня есть EJB, определяющий два представления:

  • Местный бизнес,
  • Удаленный бизнес.

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

public interface MyBusinessCommon {
    void myMethod(Object o);
}

@Local
public interface MyBusinessLocal extends MyBusinessCommon { }

@Remote
public interface MyBusinessRemote extends MyBusinessCommon { }

@Stateless
public class MyBusinessBean implements MyBusinessLocal, MyBusinessRemote {
    public void myMethod(Object o) {
        // ...
    }
}

Есть ли способ выяснить, как вызывается представление EJB из самого EJB (или его перехватчика?)

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

Я могу призвать SessionContext#getInvokedBusinessInterface() но это дает мне информацию только об объекте класса, а не об его семантике в EJB. Простого использования отражения для проверки наличия аннотаций на интерфейсах или bean-компонентах недостаточно (как насчет представлений, определенных в ejb-jar.xml?)

Я сомневаюсь, что это возможно при использовании прямой спецификации EJB, но, возможно, я кое-что пропустил.

Если нет, то возможно ли получить эту информацию от внутренностей сервера приложений? (давайте рассмотрим только JBoss AS 7.x, Glassfish 3.x и TomEE 1.5.1).

1 ответ

Решение

Это как сказал Арджан - это невозможно сделать, просто следуя спецификации EJB.

Тем не менее, в Glassfish это довольно просто сделать.

Все перехватчики EJB принимают InvocationContext параметр. InvocationContext реализация в Glassfish на самом деле com.sun.ejb.EjbInvocation учебный класс. Имеет isLocal поле, сообщающее, перехватывает ли он местный бизнес-вызов (или isRemote для удаленных деловых звонков). Вы можете использовать его, например, следующим образом:

import com.sun.ejb.EjbInvocation;

import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

@Interceptor
public class CallSourceAwareInterceptor {

    @AroundInvoke
    public Object aroundInvoke(InvocationContext ictx) throws Exception {
        boolean isLocalCall = isLocalEJBCall(ictx);

        return ictx.proceed();
    }

    boolean isLocalEJBCall(final InvocationContext ictx) {
        if (ictx instanceof EjbInvocation) {
            return ((EjbInvocation) ictx).isLocal;
        }
        else {
            throw new IllegalArgumentException("Unknown InvocationContext implementation.");
        }
    }
}

Чтобы получить доступ к этому EjbInvocation к внутреннему классу Glassfish необходимо добавить следующую зависимость maven:

<dependency>
    <groupId>org.glassfish.main.ejb</groupId>
    <artifactId>ejb-container</artifactId>
    <version>4.0.1-b02</version>
    <scope>provided</scope>
</dependency>

И вам может понадобиться добавить следующее конкретное хранилище, чтобы получить доступ к этому артефакту:

<repositories>
    <repository>
        <id>maven-promoted</id>
        <url>https://maven.java.net/content/groups/promoted/</url>
    </repository>
</repositories>

Я сделал быстрое исследование (на основе предложения Ричарда относительно Invocation объект) как добиться того же в JBoss, но не смог найти ответ...

Другие вопросы по тегам