Можно ли использовать Seam в сервисе времени JBoss? - PullRequest
4 голосов
/ 15 января 2010

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

Небольшой фрагмент, чтобы продемонстрировать, что я хочу сделать ...

@Service
public class MyService extends DefaultTimedService implements TimedObject, DefaultServiceInterface {
    @Timeout
    public void ejbTimeout(Timer timer) {
        MyInterface loader = (MyInterface) Component.getInstance(MyInterface.SEAM_NAME, true);
        // throws no context!
    }
}

Выдает, например, следующее исключение:

java.lang.IllegalStateException: No application context active
    at org.jboss.seam.Component.forName(Component.java:1945)
    at org.jboss.seam.Component.getInstance(Component.java:2005)

Ответы [ 3 ]

7 голосов
/ 01 февраля 2010

Есть один способ, который немного грязный, и есть много разработчиков, которые бы никогда не использовали такой взлом, но это решит вашу проблему:

import org.jboss.seam.contexts.Lifecycle;

@Service
public class MyService extends DefaultTimedService implements TimedObject, DefaultServiceInterface {
    @Timeout
    public void ejbTimeout(Timer timer) {
        Lifecycle.beginCall();

        MyInterface loader = (MyInterface) Component.getInstance(MyInterface.SEAM_NAME, true);
        // will not throw no context!
        // also the Component.getInstance(MyInterface.SEAM_NAME, true,true); call
        // is another way you could inject that component. 

        Lifecycle.endCall();
    }
}

Я использовал его в одном проекте, где я не мог найти ничего, что работало. Если у кого-то есть другое решение, я с нетерпением жду возможности увидеть его здесь :).

1 голос
/ 01 февраля 2010

Разве вы не можете внедрить экземпляр loader вместо того, чтобы найти его с помощью этого статического вызова? Я не совсем знаком с Seam, но, возможно (в теле класса):

@In private MyInterface loader;

, а затем, в вашем методе, просто используйте loader.

Как кажется, у Seam есть области применения / без сохранения состояния, которые в вашем случае кажутся подходящими:

@Scope(ScopeType.APPLICATION)

или

@Scope(ScopeType.STATELESS)

Попробуйте один из них - поскольку вашему классу не требуется никакой информации из сеанса / запроса, более целесообразно не использовать область действия, связанную с сетью.

Итак, определите MyService и MyInterface в одной из вышеперечисленных областей и попробуйте и инъекцию, и свой метод поиска.

Ознакомьтесь с учебником Seam по контекстам и параллелизму

Эта тема кажется полезной.

И из этой темы кажется, что есть аннотация @Asynchronous, которую вы можете использовать.

1 голос
/ 01 февраля 2010

Какую область вы определили для компонента? Вероятно, контекст приложения, как говорится, в ошибке.

...

Итак, я искал источник и обнаружил, что контексты хранятся в классе с именем Контексты . Кажется, что все контексты являются специфичными для потока, потому что они инкапсулированы в ThreadLocal-instance . Это означает, что должен быть указан для потока службы времени ...

Однако остается вопрос: как создать контекст для определенной нити.

...