While running the spring-application I got the following exception:
java.lang.ClassCastException: project.db.dbmodels.Permission cannot be cast to project.db.dbmodels.Permission
at project.db.DataOperator.setUpDefaultPermission(DataOperator.java:573)
at project.web.WebController.start(WebController.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
...
I can't recreate this Exception, while running Unit Tests.
Those are my classes: Permission:
package project.db.dbmodels;
import java.util.*;
import javax.persistence.*;
@Entity
@Table(name = "permission")
public class Permission {
@Id
@GeneratedValue
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "permission", cascade = CascadeType.ALL)
private Set<Permission_PermissionRole> permissionPermissionRole = new HashSet<Permission_PermissionRole>();
public Permission() {
}
public Permission(int id, String name, Set<Permission_PermissionRole> permissionPermissionRole) {
this.id = id;
this.name = name;
this.permissionPermissionRole = permissionPermissionRole;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Set<Permission_PermissionRole> getPermissionPermissionRole() {
return this.permissionPermissionRole;
}
public void setPermissionPermissionRole(Set<Permission_PermissionRole> permissionPermissionRole) {
this.permissionPermissionRole = permissionPermissionRole;
}
public void addPermissionPermissionRole(Permission_PermissionRole permissionPermissionRole) {
this.permissionPermissionRole.add(permissionPermissionRole);
}
public Permission id(int id) {
this.id = id;
return this;
}
public Permission name(String name) {
this.name = name;
return this;
}
public Permission permissionPermissionRole(Set<Permission_PermissionRole> permissionPermissionRole) {
this.permissionPermissionRole = permissionPermissionRole;
return this;
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Permission)) {
return false;
}
Permission permission = (Permission) o;
return id == permission.id && Objects.equals(name, permission.name)
&& Objects.equals(permissionPermissionRole, permission.permissionPermissionRole);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public String toString() {
return "{" + " id='" + getId() + "'" + ", name='" + getName() + "'" + "}";
}
}
DataOperator:
package project.db;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.PersistenceException;
import javax.persistence.RollbackException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import project.db.dbmodels.*;
import org.apache.log4j.Logger;
public class DataOperator {
final static Logger log = Logger.getLogger(DataOperator.class);
private static boolean setUpDefaultPermission(boolean change) {
SessionFactory sf = HibernateUtil.getSessionFactory();
if (sf == null) {
return false;
}
Session session = sf.openSession();
session.beginTransaction();
boolean arePermissionsReady = true;
// Setup permission "AcessAdminarea"
String request = "FROM Permission WHERE name = 'Acess Adminarea'";
Query<Permission> query = session.createQuery(request, Permission.class);
query.setMaxResults(1);
Permission permAdminArea = null;
try {
permAdminArea = query.uniqueResult();//The Exception occures here
} catch (PersistenceException e) {
return false;
}
if (permAdminArea == null) {
arePermissionsReady = false;
if (change) {
permAdminArea = new Permission();
permAdminArea.setName("Acess Adminarea");
session.save(permAdminArea);
}
}
// Setup permissionrole "Admin"
request = "FROM PermissionRole WHERE name = 'Admin'";
Query<PermissionRole> query2 = session.createQuery(request, PermissionRole.class);
PermissionRole roleAdmin = null;
try {
roleAdmin = query2.uniqueResult();
} catch (PersistenceException e) {
return false;
}
if (roleAdmin == null) {
arePermissionsReady = false;
if (change) {
roleAdmin = new PermissionRole();
roleAdmin.setName("Admin");
session.save(roleAdmin);
Permission_PermissionRole permPermrole = new Permission_PermissionRole();
permPermrole.setPermission(permAdminArea);
permPermrole.setRole(roleAdmin);
session.save(permPermrole);
}
}
// Setup permissionrole "Employee"
request = "FROM PermissionRole WHERE name = 'Employee'";
query2 = session.createQuery(request, PermissionRole.class);
PermissionRole roleEmployee = null;
try {
roleEmployee = query2.uniqueResult();
} catch (PersistenceException e) {
return false;
}
if (roleEmployee == null) {
arePermissionsReady = false;
if (change) {
roleEmployee = new PermissionRole();
roleEmployee.setName("Employee");
session.save(roleEmployee);
}
}
if (change && !arePermissionsReady) {
try {
session.getTransaction().commit();
arePermissionsReady = true;
} catch (IllegalStateException e) {
log.error(String.format("Unable to commit the transaction : %s", e.getMessage()));
} catch (RollbackException e) {
log.error(String.format("Unable to commit the transaction : %s", e.getMessage()));
}
session.close();
}
return arePermissionsReady;
}
}
While looking for the error I tried to get me some more Debug content, so I replaced the line, where the Exception ocurred and I inserted the following code into DataOperator:
Object result = query.uniqueResult();
String resultType = result.getClass().toString();
boolean test = result instanceof Permission;
boolean test2 = Permission.class.toString().equals(resultType);
I set a stop after this segment and when debugging while running it with Spring I got:
result: Permission@47 "{ id='15', name='Acess AdminArea'}"
resultType: "class project.db.dbmodels.Permission"
test: false
test2: true
While running a unit test i got:
result: Permission@47 "{ id='15', name='Acess AdminArea'}"
resultType: "class project.db.dbmodels.Permission"
test: true
test2: true
Edit: They have different class loaders. sun.misc.Launcher$AppCLassLoader and org.springframework.boot.devtools.restart.classloader.RestartClassLoader.
What can I do about that?
As mentioned by Ed Schaller in another response the problem came from the fact that the classes were loaded from two different entities.
Although, instead of changing the classpath, I found a way to fix this by using a BootstrapServiceRegistry
and adding the class loaders of both the application and hibernate.
public class HibernateUtil {
private static SessionFactory sessionFactory;
static {
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder(
createHibernateBootstrapServiceRegistry()).configure().build();
try {
sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
} catch (Exception e) {
StandardServiceRegistryBuilder.destroy(registry);
}
}
private static BootstrapServiceRegistry createHibernateBootstrapServiceRegistry() {
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
ClassLoader hibernateCl = BootstrapServiceRegistry.class.getClassLoader();
return new BootstrapServiceRegistryBuilder().applyClassLoader(tccl).applyClassLoader(hibernateCl).build();
}
public static Session openSession() {
return sessionFactory.openSession();
}
}