18

私の Java EE 6 アプリケーションは、ear ファイルにパッケージ化された war と ejb モジュールで構成されています。DI に CDI を使用しています (つまり、両方のモジュールに beans.xml ファイルがあります)。war モジュールの ejb モジュールで定義されているロギング インターセプタも使用したいと考えています。ejb の beans.xml でインターセプターを有効にしました。

<beans>
    <interceptors>
        <class>com.test.interceptor.LoggingInterceptor</class>
    </interceptors>
</beans>

これは、 ejb モジュールのインターセプタで注釈が付けられたクラスに対してのみ機能します。war モジュールのクラスはインターセプトされません (ただし、インターセプターのアノテーションも付けられます)。解決策は、戦争のインターセプターでもインターセプターを有効にすることだと思いました(上記のように)。ただし、次のメッセージが表示されてアプリケーションをデプロイできません。

SEVERE: アプリのロード中に例外が発生しました: WELD-001417 有効なインターセプター クラス クラス com.test.interceptor.LoggingInterceptor は、@Interceptor に注釈が付けられておらず、ポータブル拡張機能を介して登録されていません

私の LoggingInterceptor は次のようになります。

@Log
@Interceptor
public class LoggingInterceptor {
    private static final Logger logger =  Logger.getLogger(LoggingInterceptor.class.getName());

    static {
        logger.setLevel(Level.ALL);
    }

    @AroundInvoke
    public Object logMethod(InvocationContext ctx) throws Exception {
        logger.log(Level.FINE, "ENTRY {0} {1}",
                new Object[]{ ctx.getTarget().getClass().getName(), ctx.getMethod().getName() });
        long startTime = System.nanoTime();
        try {
            return ctx.proceed();
        } finally {
            long diffTime = System.nanoTime() - startTime;
            logger.log(Level.FINE, "RETURN {0} {1}",
                new Object[]{ ctx.getTarget().getClass().getName(), ctx.getMethod().getName() });
            logger.log(Level.FINE, "{0} took {1} ms", new Object[]{ ctx.getMethod(),
                    TimeUnit.MILLISECONDS.convert(diffTime, TimeUnit.NANOSECONDS)});
        }
    }

}

そしてインターセプターバインディング:

@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Log {}

両方のモジュールにインターセプターを使用するにはどうすればよいですか?

4

6 に答える 6

12

J2EE 7 仕様には次のように書かれています (参照):

beans.xml ファイルで指定するインターセプターは、同じアーカイブ内のクラスにのみ適用されます。@Priority アノテーションを使用して、複数のモジュールで構成されるアプリケーションのインターセプターをグローバルに指定します

このソリューションには、ベンダーに依存しないという利点があります。

例:

@Logged
@Interceptor
@Priority(Interceptor.Priority.APPLICATION)
public class LoggedInterceptor implements Serializable { ... }
于 2013-07-10T12:42:08.870 に答える
5

手遅れですが、誰かがまだこの問題を抱えている場合。少なくとも WebSphere 8b2 では、異なるモジュール間でインターセプターを使用できるようにするには、両方のモジュールを同じクラスローダーでロードする必要があります。WebSphere では、この設定は管理コンソールで切り替えることができます: [アプリケーション] > [アプリケーションの種類] > [WebSphere エンタープライズ アプリケーション] > [アプリ名] > [クラスの読み込みと更新の検出] > [WAR クラス ローダー ポリシー] = アプリケーションの単一クラス ローダー。
インターセプターは、beans.xml で一度だけ有効にする必要があります。

于 2011-04-18T15:10:28.790 に答える
1

あなたの WAR には、ejb-jar へのクラスローダーの可視性が欠けているのだろうか? 理想的には、299 個のインターセプターが独自の jar にあり、EJB と Web モジュールの両方に表示され、両方の beans.xml で有効になると思います。

于 2011-01-08T14:22:22.590 に答える
0

JBoss AS 6.0 / 6.1 (夜間ビルド) で同じ問題が発生し、個別のクラスローダーを無効にすることで修正しました(オプション 1) が、これには細心の注意を払ってください。クラスローダの分離は理由もなく導入されていないため、今後、新しい問題が発生するようです...

これはジラ レポートです。投票してください :-)

于 2011-04-20T11:29:02.500 に答える
0

JBoss 7のロギング インターセプターでまったく同じ問題が発生し、完全なインターセプターの jar をアプリケーションにオーバーレイすることで修正しました。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <overlays>
                    <overlay>
                        <groupId>com.github.t1</groupId>
                        <artifactId>logging-interceptor</artifactId>
                        <type>jar</type>
                        <targetPath>WEB-INF/classes</targetPath>
                    </overlay>
                </overlays>
            </configuration>
        </plugin>
    </plugins>
</build>

<dependencies>
    <dependency>
        <groupId>com.github.t1</groupId>
        <artifactId>logging-interceptor</artifactId>
        <version>1.1</version>
        <optional>true</optional>
    </dependency>
</dependencies>

アプリケーションのbreans.xml.

良くありませんが、うまくいきます。Java EE 7 では、インターセプターに@Priority.

于 2014-04-27T21:05:36.623 に答える