私は最初のJava EEアプリケーションをJSF、PrimeFaces、Glassfish、Netbeansを使用して構築しています。私は新しいので、コアの問題に間違ってアプローチしている可能性があります。
主要な問題:ユーザーの情報を安全に維持したい。 JSFセッションBeanで維持するか、ステートフルセッションEJBで維持するかについては、矛盾する考えがあるようです。ステートフルセッションEJBを使用しようとしています。その方が、より安全だからです。
問題は、アプリケーションがそのBeanを作成して再利用することを期待しているときに、そのBeanの複数のインスタンスを作成しているように見えることです。ページを更新すると、@PostConstruct
と@PostActivate
が3回実行され、それらはすべて異なるインスタンスで実行されます。その後、アプリケーションを再デプロイすると、それらはすべて破棄されます。
それがどのように機能するかを誤解しましたか、または何かが間違って構成されていますか?
切り捨てられたコードサンプルを表示してみます。
basic.xhtml
:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://Java.Sun.com/jsf/html"
xmlns:c="http://Java.Sun.com/jsp/jstl/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
Hello from Facelets
<c:if test="#{loginController.authenticated}">
Authenticated
</c:if>
<c:if test="#{loginController.authenticated}">
Authenticated
</c:if>
<c:if test="#{loginController.authenticated}">
Authenticated
</c:if>
</h:body>
</html>
LoginController
:
@Named(value = "loginController")
@RequestScoped
public class LoginController implements Serializable {
@EJB
private UserBeanLocal userBean;
public boolean isAuthenticated() {
return userBean.isAuthenticated();
}
}
UserBean
(UserBeanLocal
インターフェースを除く)
@Stateful
public class UserBean implements UserBeanLocal, Serializable {
boolean authenticated = false;
@PostConstruct
@PostActivate
public void setup(){
System.out.println("##### Create user Bean: "+this.toString());
}
@Override
public boolean isAuthenticated() {
System.out.println("########## Authentication test is automatically passing.");
authenticated = true;//hard coded for simplicity.
return authenticated;
}
@PrePassivate
@PreDestroy
public void cleanup(){
System.out.println("##### Destroy user Bean");
}
}
最後に、3回更新した後のGlassfishの出力は次のとおりです。
INFO: ##### Create user Bean: boundary._UserBean_Serializable@2e644784
INFO: ########## Authentication test is automatically passing.
INFO: ########## Authentication test is automatically passing.
INFO: ########## Authentication test is automatically passing.
INFO: ##### Create user Bean: boundary._UserBean_Serializable@691ae9e7
INFO: ########## Authentication test is automatically passing.
INFO: ########## Authentication test is automatically passing.
INFO: ########## Authentication test is automatically passing.
INFO: ##### Create user Bean: boundary._UserBean_Serializable@391115ac
INFO: ########## Authentication test is automatically passing.
INFO: ########## Authentication test is automatically passing.
INFO: ########## Authentication test is automatically passing.
ステートフルセッションBean(SFSB)は、あなたが思っているものとは異なります。セッションスコープのJSFマネージドBeanのように動作すると思われるかもしれません。これは真実ではありません。 EJBの「セッション」という用語は、あなたが考えていたHTTPセッションとはまったく異なる意味を持っています。
EJBの「セッション」は、トランザクションコンテキストで解釈する必要があります。 SFSBの場合、クライアントが存続している限り、トランザクション(基本的にはDBセッション)は存続します。 SFSBのクライアントは、特定の例ではなくWebブラウザーですが、JSFマネージドBeanインスタンス自体、まさにSFSBが注入されたインスタンスです。 JSFマネージドBeanをリクエストスコープに配置したため、SFSBは、JSFマネージドBeanとともにすべてのHTTPリクエストで再作成されます。
例として、JSFマネージドBeanをビュースコープに配置してみてください。ビュースコープは、たとえば、同じページのマルチステップフォームに役立ちます。ビューがそれ自体にポストバックするたびに、同じJSFマネージドBeanインスタンスが再利用され、このインスタンスにより、SFSBの同じインスタンスにアクセスできます。 Beanが作成されたときであり、他の場所で共有されていません。 SFSBトランザクションは、クライアント(ビュースコープのJSFマネージドBean)が存続する限り存続します。
ステートレスセッションBean(SLSB)は他の場所で共有できますが、とにかくステートレスとして扱われることを目的としているため、これは問題ではありません。この「機能」は、コンテナを作成および保存するための時間とメモリを節約します。コンテナはそれらのプールを持つことができます。さらに、ビュー、セッション、またはアプリケーションスコープのJSFマネージドBeanに挿入されるSLSBインスタンスは、JSFマネージドBeanの作成時とまったく同じインスタンスをすべてのHTTPリクエストで参照する必要はありません。コンテナのプールで使用可能なインスタンスによっては、完全に異なるインスタンスになることもあります。トランザクションは、SLSBで単一のメソッドが呼び出される限り(デフォルトで)存続します。
とはいえ、SFSBは、「ログインしたユーザーを記憶する」という特定のケースには適していません。それが「より安全」であるということは、実際には意味がありません。 JSFマネージドBeanをセッションスコープに配置し、ログインしたユーザーをそれ自体で記憶させ、SLSBを使用してビジネスアクション(DBとの対話など)を実行し、必要な場合にのみSFSBを使用しますrealステートフルセッションBean(nowはそれらが正確に何であるかを理解していると思います:))。
私の調査と使用法から理解できる限り、EJB SFSBはJSFであるため、Webアプリケーションには役立ちません。Springはユーザーごとのセッションを維持するためにhelfullアノテーションを提供します。ただし、WebサービスとRPCメソッドの呼び出し呼び出しが必要なアプリケーションが実行されている場合、EJB SFSBは、ユーザーごとのセッション(トランザクション)を維持するために必要です。