3

JBoss AS7で実行すると、次のようになります。

import javax.inject.Singleton;

@Singleton
public class Connections {
    private final List<AtmosphereResource> connections = new ArrayList<AtmosphereResource>();

    public void add(AtmosphereResource event) {
        connections.add(event);
    }
}

この:

import javax.inject.Inject;

public class PubSubAtmosphereHandler extends AbstractReflectorAtmosphereHandler {
    @Inject
    private Connections connections;

    @Override
    public void onRequest(AtmosphereResource event) throws IOException {
        [...]
        connections.add(event); // <---
}

指定回線上のNPE。数え切れないほどのページと例を読んだ後、これは何十回も繰​​り返される方法の1つですが、それでも機能しません。空のbeans.xmlをWEB-INFに配置しました。ここで何が欠けていますか?

4

3 に答える 3

3

いくつかの調査の結果、Atmosphereはこの種の機能に(現在壊れている)フックを提供していることがわかりました。つまり、「外部」のインスタンス化にもかかわらず、通常のアノテーションを使用してAtmosphereで機能させることが可能です

コードがデプロイされる場所がわかっている場合は、同じパッケージに同じ名前のクラスを配置し、適切なインジェクターを提供することで、AtmosphereのデフォルトのnoopInjectorProviderクラスを上書きできます。

この回答の最後にJBossAS7のコードと、自分でテストしていないGoogleGuiceとSpringで動作するはずのコードへのリンクを追加しています。

コードを複数のプラットフォームで動作させる必要がある場合は、実行しているものを検出して適切なインジェクターを返す方法を理解する必要があります。私はGuiceとSpringにあまり詳しくないので、その演習は読者に任せます。

JBoss AS7のダーティな「最初のドラフト」コード(デフォルトのnoopプロバイダーを上書きするには、これを宣言されたパッケージに入れる必要があることに注意してください):

package org.atmosphere.di;

import java.util.NoSuchElementException;
import java.util.ServiceLoader;

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class InjectorProvider {

    private InjectorProvider() {}

    public static Injector getInjector() {
        return LazyProvider.INJECTOR;
    }

    private static final class LazyProvider {
        private static final Injector   INJECTOR;

        static {
            Injector injector = new Injector() {
                @Override public void inject(final Object o) {
                    try {
                        final BeanManager bm = (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
                        final CreationalContext cc = bm.createCreationalContext(null);
                        final InjectionTarget it = bm.createInjectionTarget(bm.createAnnotatedType(o.getClass()));
                        it.inject(o, cc);
                        cc.release();
                    } catch (final NamingException e) {
                        e.printStackTrace();
                    }
                }
            };
            try {
                injector = ServiceLoader.load(Injector.class).iterator().next();
            } catch (final NoSuchElementException e) {}
            INJECTOR = injector;
        }
    }
}

ラッピングコードはAtmosphereコードベースから取得され、Javaでシングルトンを実行するための非常に悪い方法であることに注意してください。おそらく、これを「そのまま」本番環境で使用したくないでしょう。

Guiceインジェクター、未テスト:https ://github.com/Atmosphere/atmosphere/blob/atmosphere-1.0.x/extras/guice/src/main/java/org/atmosphere/guice/GuiceInjector.java

スプリングインジェクター、未テスト:https ://github.com/Atmosphere/atmosphere/blob/atmosphere-1.0.x/extras/spring/src/main/java/org/atmosphere/spring/SpringInjector.java

于 2013-01-17T15:31:50.210 に答える
2

他の人が言おうとしているのは、PubSubAtmosphereHandlerのライフサイクルはコンテナー(別名JBoss)によって制御される必要があるということです。

つまり、コンテナはPubSubAtmosphereHandlerのインスタンスの作成と初期化を担当します。

あなたまたはあなたのフレームワークがこのオブジェクトを作成した場合、インジェクションは行われません。

于 2012-12-12T13:03:34.897 に答える
0

jndiを使用してBeanManagerを取得できる場合があります。次に、そこからBeanを取得できます。

BeanManager bm = initialContext.lookup("java:comp/BeanManager");
Bean<Connections> bean = (Bean<Connections>) bm.getBeans(Connections.class).iterator().next();
CreationalContext<Connections> ctx = bm.createCreationalContext(bean);

Connections connections = (Connections) bm.getReference(bean, Connections.class, ctx);
connections.add(event);
于 2012-12-13T16:51:50.047 に答える