0

こんにちは、StackOverFlowの仲間です。JavaEnterpriseBeansやJavaPersistenceAPIなどのテクノロジを使用してWeb対応アプリケーションをプログラムする方法を学び始めたところです。

NetBeansの公式Webサイトでは、現在、(おそらく)上記のアプリケーションの開発を可能にするバンドルを提供しています。およそ213MBのサイズのバンドル。

これが取引です。Webサイトにログインするプロセスをシミュレートしたいとします。たとえば、Amazonにログインすると、セッションデータがブラウザに保存されます。これにより、「ようこそ、ミゲルマルティンス」、「ミゲルマルティンスのおすすめの購入」などを表示できます。 、 右?右。さて、これが私がすることです(index.jspから始めましょう):

<%@page import="beans.UserBeanRemote"%>
<%@page import="entities.SimplifiedUser"%>
<%@page import="beans.BeanFacade"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <%
            UserBeanRemote userBean = BeanFacade.getUserBean();
            userBean.setAuthenticatedUser(session, new SimplifiedUser("Miguel Martins", "password"));
            SimplifiedUser authenticatedUser = userBean.getAuthenticatedUser(session);
            if (authenticatedUser == null) {
                out.write("No user is authenticated.");
            }
            else {
                out.write("There is an authenticated user. Username: " + authenticatedUser.getUserName());
            }
        %>
    </body>
</html>

簡単ですよね?ここでの私の意図は、(明らかに)setAuthenticatedUserメソッドを呼び出してセッションデータを格納し、次にgetAuthenticatedUserメソッドを呼び出して基本的に「このWebブラウザーで誰が認証されているか」を尋ねることです。

そして、これが私が残りをプログラムした方法です。これは、学習目的のための単純で最小限のアプリケーションであると想定されていることに注意してください。

BeanFacade.java

package beans;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class BeanFacade {
    private static InitialContext context;

    private static void initializeContext() throws NamingException {
        if (context == null) {
            context = new InitialContext();
        }
    }

    public static UserBeanRemote getUserBean() throws NamingException {
        initializeContext();
        return (UserBeanRemote) context.lookup("java:global/SimplifiedAuthentication/SimplifiedAuthentication-ejb/UserBean!beans.UserBeanRemote");
    }
}

UserBean.java

package beans;

import entities.SimplifiedUser;
import javax.ejb.Stateless;
import javax.servlet.http.HttpSession;

@Stateless
public class UserBean implements UserBeanRemote {

    @Override
    public void setAuthenticatedUser(HttpSession session, SimplifiedUser user) {
        session.setAttribute("authenticated_user", user);
    }

    @Override
    public SimplifiedUser getAuthenticatedUser(HttpSession session) {
        return (SimplifiedUser) session.getAttribute("authenticated_user");
    }
}

UserBeanRemote.java(明らかに、UserBeanのリモートインターフェイス)

package beans;

import entities.SimplifiedUser;
import javax.ejb.Remote;
import javax.servlet.http.HttpSession;

@Remote
public interface UserBeanRemote {
    public void setAuthenticatedUser(HttpSession session, SimplifiedUser user);
    public SimplifiedUser getAuthenticatedUser(HttpSession session);
}

最後になりましたが、SimplifiedUser.javaです。これがセッションデータとして保存したいものです。

package entities;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class SimplifiedUser implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    private String userName;
    private String password;

    public SimplifiedUser() {
    }

    public SimplifiedUser(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    public String getUserName() {
        return userName;
    }
}

ただし、残念なことに、プロジェクトを実行すると、例外がスローされます。

HTTPステータス500-

タイプ例外レポート

メッセージ

descriptionサーバーで内部エラー()が発生したため、この要求を実行できませんでした。

例外

org.apache.jasper.JasperException:javax.ejb.EJBException:java.rmi.MarshalException:CORBABAD_PARAM1330446342たぶん; ネストされた例外は次のとおりです。java.io.NotSerializableException:

根本的な原因

javax.ejb.EJBException:java.rmi.MarshalException:CORBABAD_PARAM1330446342たぶん; ネストされた例外は次のとおりです。java.io.NotSerializableException:

根本的な原因

java.rmi.MarshalException:CORBABAD_PARAM1330446342たぶん; ネストされた例外は次のとおりです。java.io.NotSerializableException:

根本的な原因

java.io.NotSerializableException:

根本的な原因

org.omg.CORBA.BAD_PARAM:vmcid:OMGマイナーコード:6完了:たぶん

注例外とその根本原因の完全なスタックトレースは、GlassFish Server Open SourceEdition3.0.1ログで入手できます。GlassFishサーバーオープンソースエディション3.0.1

そして、いくつかの昔ながらのデバッグ(「コメントアウト」)の後、例外の原因は次のように思われます。

session.setAttribute("authenticated_user", user);

この:

return (SimplifiedUser) session.getAttribute("authenticated_user");

これは、どういうわけか、HttpSessionインスタンス内にユーザーデータを保存する(または取得する)ことを望んでいないことを示しています。

なぜこれなのか誰か知っていますか?そもそも、SerializableオブジェクトをHttpSessionインスタンス内に格納することは完全に合法ではありませんか?もしそうなら、世界で何が起こっているのでしょうか?

ありがとう、ミゲル・マルティンス

4

1 に答える 1

0

StackOverflowのメンバーの皆さん、お詫び申し上げます。私とプロジェクトの同僚の1人との間で非常に啓発的な話し合いをした後、私は自分のやり方の誤りに気づきました。簡単に言えば、例外は、EJBに渡すすべてのものがシリアル化可能でなければならないという事実によるもののようです。そして当然、HttpSessionインスタンスはシリアル化できません。

ただし、シリアル化可能であったとしても、私の同僚は、疑いの余地なく、HttpSessionインスタンスがWeb層を離れて他の層(この場合はEJB層)に渡されてはならないことを明確に証明しました。 )。したがって、私がやろうとしていたことは...私はそれを間違った方法でやっていた。

私の同僚自身によると、正しい方法は、Web層でのみ使用されるまったく新しいUserクラスを作成することです(つまり、@ Entityアノテーションを運ぶUserクラスと別のクラスの2つのクラスができあがります) 、後に「UserViewModel」と呼ばれるようになり、ViewModelパターンと呼ばれるデザインパターンに従います。基本的に、この「2番目のUserクラス」は、元のユーザークラスの縮小版であり、Web層でのみ使用するように設計されています。

それで、私のやり方の誤りを私に見せてくれた私の同僚に称賛を送ります。しかし、誰かがこれについて何か他に言うことがあるなら、声を上げてください。

于 2010-10-12T21:01:17.290 に答える