Glassfish v3 + NetBeans +简单身份验证模拟器:为什么我会收到与序列化相关的异常?
大家好,StackOverFlow 的成员们。我刚刚开始学习如何使用 Java Enterprise Beans 和 Java Persistence API 等技术对支持 Web 的应用程序进行编程。
NetBeans 官方网站目前提供了一个捆绑包(据称)允许我开发上述应用程序。大小约为 213 MB 的捆绑包。
现在事情是这样的:假设我想模拟登录网站的过程。你知道,当我登录亚马逊时,我的会话数据存储在我的浏览器中,这就是他们能够显示“欢迎,米格尔·马丁斯”或“米格尔·马丁斯推荐购买”等内容的方式, 正确的?正确的。好吧,这就是我所做的(让我们从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 -
类型异常报告
消息
描述服务器遇到了 阻止它的内部错误 () 满足此请求。
异常
org.apache.jasper.JasperException: javax.ejb.EJBException: java.rmi.MarshalException:CORBA BAD_PARAM 1330446342 也许;嵌套的 例外是: java.io.NotSerializedException:
根本原因
javax.ejb.EJBException: java.rmi.MarshalException:CORBA BAD_PARAM 1330446342 也许;嵌套的 例外是: java.io.NotSerializedException:
根本原因
java.rmi.MarshalException:CORBA BAD_PARAM 1330446342 也许;嵌套的 例外是: java.io.NotSerializedException:根本原因
java.io.NotSerializedException:
根本原因
org.omg.CORBA.BAD_PARAM:vmcid:OMG 次要代码:6 完成:也许
注意完整的堆栈跟踪 异常及其根本原因是 在 GlassFish Server Open 中可用 源版本3.0.1日志。玻璃鱼 服务器开源版3.0.1
并且,经过一些老式的调试(“注释掉一些东西”),异常的原因似乎是这样的:
session.setAttribute("authenticated_user", user);
这
return (SimplifiedUser) session.getAttribute("authenticated_user");
表明我,不知何故,他们不想要我将我的用户数据存储(也不检索它)在 HttpSession 实例中。
有谁知道这是为什么?首先将 Serialized 对象存储在 HttpSession 实例中不是完全合法的吗?如果是这样,那么这里到底发生了什么?
谢谢你, 米格尔·马丁斯
Greetings, fellow StackOverFlow members. I have just begun to learn how to program web-enabled applications using technologies such as Java Enterprise Beans and Java Persistence API.
The official NetBeans website currently offers a bundle that (supposedly) allows me to develop said applications. A bundle that has an approximate size of 213 MB.
Now here's the deal: suppose that I want to simulate the process of logging in to a website. You know, like, when I log into Amazon, my session data is stored in my browser, and that is how they're able to, like, display things such as "Welcome, Miguel Martins" or "Recommended purchases for Miguel Martins", right? Right. Well, here's what I do (let's start with 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>
Simple, right? My intentions here are (obviously) to call the setAuthenticatedUser method to store session data, and then the getAuthenticatedUser method to basically ask "who is authenticated in this web browser?"
And here's how I programmed the rest. Keep in mind this is supposed to be a simple/minimalistic application, for learning purposes.
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 (obviously, UserBean's remote interface)
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);
}
And last, but not least, SimplifiedUser.java. This is what I want to store as session data.
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;
}
}
However, much to my dismay, when I run the project, it throws an exception at me:
HTTP Status 500 -
type Exception report
message
descriptionThe server encountered an
internal error () that prevented it
from fulfilling this request.exception
org.apache.jasper.JasperException:
javax.ejb.EJBException:
java.rmi.MarshalException: CORBA
BAD_PARAM 1330446342 Maybe; nested
exception is:
java.io.NotSerializableException:root cause
javax.ejb.EJBException:
java.rmi.MarshalException: CORBA
BAD_PARAM 1330446342 Maybe; nested
exception is:
java.io.NotSerializableException:root cause
java.rmi.MarshalException: CORBA
BAD_PARAM 1330446342 Maybe; nested
exception is:
java.io.NotSerializableException:root cause
java.io.NotSerializableException:
root cause
org.omg.CORBA.BAD_PARAM: vmcid: OMG
minor code: 6 completed: Maybenote The full stack traces of the
exception and its root causes are
available in the GlassFish Server Open
Source Edition 3.0.1 logs. GlassFish
Server Open Source Edition 3.0.1
And, after some old-fashioned debugging ("commenting stuff out"), it seems that the cause of the exception is this:
session.setAttribute("authenticated_user", user);
And this:
return (SimplifiedUser) session.getAttribute("authenticated_user");
Which indicates me that, somehow, they don't want me to store my user data (nor retreive it) inside an HttpSession instance.
Does anyone know why this is? Isn't it perfectly legal to store a Serializable object inside an HttpSession instance in the first place? If so, then what in the world is going on here?
Thank you,
Miguel Martins
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
抱歉,各位 StackOverflow 成员。经过我和一位项目同事之间的一些非常有启发性的讨论后,我意识到我的方法是错误的。长话短说,这个异常似乎是由于我传递给 EJB 的所有内容都必须是可序列化的。当然,HttpSession 实例是不可序列化的。
即使它是可序列化的,我的那位同事毫无疑问地向我清楚地证明了 HttpSession 实例永远不应该离开 Web 层并传递到其他层(在本例中为 EJB 层) )。因此,我想做的事......我的方式是错误的。
根据我的同事本人的说法,正确的方法是创建一个全新的 User 类,专门在 Web 层使用(即我们最终有两个类,一个 User 类,它带有 @Entity 注释,另一个类,后来被称为“UserViewModel”,遵循称为 ViewModel 模式的设计模式 基本上,这个“第二个 User 类”是原始类的简化版本,专门用于 Web 层。 .
感谢我的同事,他向我展示了我的方法的错误,如果有人对此还有什么要说的,请大声说出来。
My apologies, fellow StackOverflow members. After some very enlightening discussion between me and one of my project colleagues, I have realized the error of my ways. Long story short, it seems that the exception is due to the fact that everything I pass around to an EJB has to be serializable. And naturally, an HttpSession instance is not serializable.
Even if it were serializable, though, that colleague of mine clearly proved to me, beyond the shadow of a doubt, that an HttpSession instance should never leave the web tier and be passed around to some other tier (in this case, the EJB tier). Hence, what I was trying to do... I was doing it the wrong way.
The correct way, according to my colleague himself, is to create a whole new User class, to be used exclusively in the web tier (i.e. we end up having two classes, a User class, which carries the @Entity annotation, and another class, which would later be known as "UserViewModel", following a design pattern known as the ViewModel pattern. Basically, this "second User class" is a reduced version of the original one, designed to be exclusively used on the web tier.
So kudos to my colleague who showed me the error of my ways. If anyone out there has something else to say about this, though, please do speak up.