【发布时间】:2011-11-10 11:03:01
【问题描述】:
我必须将两个 tomcat 服务器(tcat01 和 tcat02)放在负载平衡架构中。
我使用的是 tomcat 6.x,我在 tomcat tcat01 上像这样编辑了 conf/server.xml:
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tcat01">
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="6"/>
....
在 tcat02 上 conf/server.xml 是这样的:
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tcat02">
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="6"/>
....
我启动了tcat01,然后是tcat02,il catalina.out 看来tcat01 和tcat02 通信很好。
然后我用互联网导航器连接到 webapp,然后每次我在 webapp 中做某事(我的意思是当我导航时)都会出现这个异常:
Nov 24, 2011 12:00:13 AM org.apache.catalina.core.ContainerBase backgroundProcess
WARNING: Exception processing manager org.apache.catalina.ha.session.DeltaManager@278c4835 background process
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mycompany.myproject.model.authentification.Authority.groups, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
at org.hibernate.collection.PersistentSet.toString(PersistentSet.java:332)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
这里是不能sezialized类的代码(即堆栈跟踪中提到的java bean):
import static javax.persistence.GenerationType.IDENTITY;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
@Entity
@Table(name = "authority", uniqueConstraints = @UniqueConstraint(columnNames = "name"))
public class Authority implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -7436593455923433675L;
//SYSTEM ROLE CONSTANT
public static final String MANAGER_SYSTEM_ROLE = "ROLE_MANAGER";
public static final String CLIENT_SYSTEM_ROLE = "ROLE_CLIENT";
public static final String PEDAGO_ADMIN_SYSTEM_ROLE = "ROLE_PEDAGO_ADMIN";
private Integer id;
@Size(min=1)
@Pattern(regexp="^ROLE[_a-zA-Z]+$", message="{authority.name.pattern.error}")
private String name;
@Size(max=65535)
private String description;
private Boolean isSystem;
private Set<Group> groups = new HashSet<Group>(0);
public Authority() {
this.isSystem = false;
}
public Authority(String name) {
this.name = name;
this.isSystem = false;
}
public Authority(String name, String description, Set<Group> groups) {
this.name = name;
this.description = description;
this.groups = groups;
this.isSystem = false;
}
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name = "name", unique = true, nullable = false, length = 45)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "description")
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public void setIsSystem(Boolean isSystem) {
this.isSystem = isSystem;
}
@Column(name = "system")
public Boolean getIsSystem() {
return isSystem;
}
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "group_authorities", joinColumns = { @JoinColumn(name = "authority_id", nullable = false, updatable = true) }, inverseJoinColumns = { @JoinColumn(name = "group_id", nullable = false, updatable = true) })
public Set<Group> getGroups() {
return this.groups;
}
public void setGroups(Set<Group> groups) {
this.groups = groups;
}
@PrePersist
protected void updateSystemField() {
if(isSystem == null)
isSystem = false;
}
}
这里是 java bean Group 的代码(因为我们在 Groups 集合上有一个延迟初始化异常):
import static javax.persistence.GenerationType.IDENTITY;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Entity
@Table(name = "groups", uniqueConstraints = @UniqueConstraint(columnNames = "name"))
public class Group implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 7380068327050752558L;
private Integer id;
@NotNull
@Size(min=1)
private String name;
private String description;
private Boolean isSystem;
private Set<Authority> authorities = new HashSet<Authority>(0);
private Set<User> users = new HashSet<User>(0);
public Group() {
this.isSystem = false;
}
public Group(String name) {
this.name = name;
this.isSystem = false;
}
public Group(String name, String description, Set<Authority> authorities, Set<User> users) {
this.name = name;
this.description = description;
this.isSystem = false;
this.authorities = authorities;
this.users = users;
}
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name = "name", unique = true, nullable = false, length = 45)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "description")
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public void setIsSystem(Boolean isSystem) {
this.isSystem = isSystem;
}
@Column(name = "system")
public Boolean getIsSystem() {
return isSystem;
}
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "group_authorities", joinColumns = { @JoinColumn(name = "group_id", nullable = false, updatable = true) }, inverseJoinColumns = { @JoinColumn(name = "authority_id", nullable = false, updatable = true) })
public Set<Authority> getAuthorities() {
return this.authorities;
}
public void setAuthorities(Set<Authority> authorities) {
this.authorities = authorities;
}
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "group_users", joinColumns = { @JoinColumn(name = "group_id", nullable = false, updatable = true) }, inverseJoinColumns = { @JoinColumn(name = "user_id", nullable = false, updatable = true) })
public Set<User> getUsers() {
return this.users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public void addAuthority(Authority authority) {
if(authorities == null)
authorities = new HashSet<Authority>(0);
authorities.add(authority);
}
public boolean removeAuthority(Authority authority) {
return authorities == null || authorities.remove(authority);
}
public void addUser(User user) {
if(users == null)
users = new HashSet<User>(0);
users.add(user);
}
public boolean removeUser(User user) {
return users == null || users.remove(user);
}
@PrePersist
protected void updateSystemField() {
if(isSystem == null)
isSystem = false;
}
}
感谢您的帮助
【问题讨论】:
-
看起来tomcat正在尝试序列化会话并且会话中有无法序列化的属性,我建议您查看正在添加到会话的对象并查看它们是否可以序列化.
-
你说得对,我在谷歌上找到了 JVM 的选项“-Dsun.io.serialization.extendedDebugInfo=true”。当我添加这个选项时,我看到了哪些对象不能被序列化。我不知道我是否可以在 stackoverflow 中更改我的问题的详细信息,如果我不能,我将创建另一个问题。关于哪些对象不能序列化:带有惰性集合的java bean,其实我有一个惰性异常!我的懒集合不能序列化,不知道怎么解决这个问题。
-
能不能把不能序列化的对象的代码贴出来,只要对象实现了java.io.Serializable接口就可以序列化了。
-
好的,我做到了,我编辑了我的原始帖子,以便提供更好的堆栈跟踪(因为我激活了 JVM 参数 sun.io.serialization.extendedDebugInfo=true)
-
我认为@Chris 是对的,如果您不想更改映射,请在加载授权后查看 Hibernate.initialize 进行初始化。 javalobby.org/java/forums/t62077.html
标签: java tomcat serialization load-balancing session-replication