I'm getting the following error:
Code:
Nested in org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'populator' defined in class path resource [spring-core.xml]: Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanInitializationException: Initialization of DAO failed; nested exception is org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions:
org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
I thinking that I'm not using spring transactions properly, but am not sure how to solve it. The problem occurs at the following line in BootstrapDataPopulator.java:
getSession().save(m);
Any help would be appreciated!
Here's the code:
## Spring-hibernate configCode:
<!-- Enable annotation configuration -->
<context:annotation-config/>
<!-- Scan packages for Spring annotations -->
<context:component-scan base-package="myapp.service"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<!-- ommitted -->
</bean>
<!-- Transaction support beans -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Spring AOP auto-proxy creation (required to support Shiro annotations) -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<!-- Populates the database with default data. -->
<bean id="populator" class="myapp.service.BootstrapDataPopulator">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Post processor that automatically invokes init() and destroy() methods -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
## myapp.service.BootstrapDataPopulator.javaCode:
@Transactional
public class BootstrapDataPopulator extends HibernateDaoSupport {
private static final Logger log = LoggerFactory.getLogger(BootstrapDataPopulator.class);
public void initDao() throws Exception {
buildRolesData();
buildMemberData();
}
private static final String[][] ROLES = {
{"member"},
{"manager"},
{"admin"}
};
private void buildRolesData() {
log.debug("Building Roles Data");
for (int i = 0; i < ROLES.length; i++) {
Role r = new Role(ROLES[i][0]);
getSession().save(r);
}
}
private static final String[][] MEMBERS = {
{"tom","Tom","Smith"},
{"member","Sue","Stark"},
{"admin","Mark","Brisk"}
};
private static final String[][] MEMBER_ROLES = {
{
"member","manager"
},
{
"member"
},
{
"member","manager","admin"
}
};
private void buildMemberData() {
log.debug("Building Member Data");
for (int i = 0; i < MEMBERS.length; i++) {
Member m= new Member();
m.setUsername(MEMBERS[i][0]);
m.setPassword(MEMBERS[i][0]);
for (int j = 0; j < MEMBER_ROLES[i].length; j++) {
Role r = (Role) getSession().createCriteria(Role.class)
.add(Restrictions.eq("name", MEMBER_ROLES[i][j]))
.uniqueResult();
if (r != null) {
m.addRole(r);
}
}
getSession().save(m);
}
}
}
## myapp.model.Member.javaCode:
@Entity
@Table(name="members")
@Cache(usage= CacheConcurrencyStrategy.READ_WRITE)
public class Member extends AbstractEntity {
private static final long serialVersionUID = 1L;
private String username;
private String password;
private Set<Role> roles = new HashSet<Role>();
public Member() {
super();
}
@Basic(optional=false)
@Column(length=100)
@Index(name="idx_members_username")
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Basic(optional=false)
@Column(length=255)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="members_roles")
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public Set<Role> getRoles() {
return this.roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public Role hasRole(Role role) {
if (this.roles.contains(role)) {
return role;
}
return null;
}
public boolean addRole(Role role) {
return this.roles.add(role);
}
public boolean removeRole(Role role) {
return this.roles.remove(role);
}
}
## myapp.model.Role.javaCode:
@Entity
@Table(name="roles")
@Cache(usage= CacheConcurrencyStrategy.READ_WRITE)
public class Role implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
protected Role() {
}
public Role(String name) {
this.name = name;
}
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Basic(optional=false)
@Column(length=100)
@Index(name="idx_roles_name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}