少し混乱しています。 javax.inject.Singleton
とjavax.ejb.Singleton
の正確な違いは何ですか?
もっともらしい説明を見つけました ここ :
デフォルトでは、
javax.ejb.Singleton
セッションBeanはトランザクション(EJB 3.1仕様のセクション13.3.7)であり、すべてのビジネスメソッド呼び出し(セクション4.8.5.4および4.8.5.5)に対して排他ロックの取得が必要です。対照的に、
javax.inject.Singleton
はトランザクションではなく、コンテナ管理の同時実行性をサポートしていません(主な結果は、コンテナによってロックスキームが実装されていないことです)。 [...]EJB機能が必要ない場合は、
@ApplicationScoped
(javax.inject.Singleton
はCDIによって定義されていないため、そのセマンティクスはその仕様に準拠していません)。
将来の混乱を減らすために、この小さなユニットテストを使用します(最初のレベルのパッケージ名を置き換える必要があります)。
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import org.junit.Test;
public class SingletonTest {
/** requires com.tngtech.archunit:archunit-junit:0.4.0 */
@Test
public void detectWrongSingletonAnnotation() {
final ClassFileImporter importer = new ClassFileImporter();
final JavaClasses classes = importer.importPackages("first_level_package");
noClasses().should().beAnnotatedWith("javax.inject.Singleton")
.as("Please use javax.ejb.Singleton instead of javax.inject.Singleton.")
.check(classes);
}
}
受け入れられた答えは私の問題を解決しなかったので、私は自分の答えを投稿します。 Adam Bienの記事ほどではありませんが、間違いなくより実用的です。
次のコードを検討してください。
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
@Singleton
public class DatabaseConnection {
@PostConstruct
public void init() {
System.out.println("init");
}
public ChampionComp getFirstRecord() {
return new ChampionComp("Ashe", "Teemo", "Warwick",
"Blitzcrank", "Syndra", "Anivia", "Brand", "Rammus", "Xin Zhao", "Irelia");
}
}
そして、これRESTサービス:
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
@Path("/champions")
public class ChampionsAPI {
@Inject
private DatabaseConnection db;
@GET
@Produces("text/plain")
public String getClichedMessage() {
ChampionComp comp = db.getFirstRecord();
return comp.toString();
}
}
javax.ejb.Singleton
を使用すると、このコードは問題なく機能します。 DatabaseConnection
インスタンスは一度作成され、RESTサービスに挿入されます。ただし、インポートのejb
をinject
に置き換えると、ChampionsAPIでNPEを受け取ります。 dbフィールドへのアクセス中のクラス-これは、シングルトンが作成されなかったためです(何らかの理由で、おそらくjavax.inject.Singleton
?の使用中にインターフェイスを使用する必要があるため)。