Issue
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?
Solution
This happens when the class in question is being loaded from two (or more) class loaders. A class in java is only unique when combined with it's class loader. Likely your Permission class is getting loaded from one class loader and then it is being cast to the same class but loaded from a different class loader.
Add the class loader to your debug logs and you'll likely see the problem and hopefully which class loaders the class is being loaded by.
Answered By - Ed Schaller
Answer Checked By - Willingham (JavaFixing Volunteer)