2

I'm trying to compare two identical objects. When the page first loads, they are equal, however when I refresh the page a second time, the do not equal each other despite the data or object not changing.

What I'm doing.

I have a CurrentUser obj that I store in the user session at login. I use the currentUser to compare against the assignedUser of a form. If the currentUser.equals(pr.getAssignedUser()) then I enable access. AssignedUser is a hibernate variable reference to CurrentUser. If I remove getClass() != obj.getClass from my equals override and just use property comparisons, everything works fine.

The thing that concerns me most is it works on the first access, however it doesn't on a page refresh. Without knowing what is going on, I worry about a memory leak.

Does anybody know what might be going on here?

CurrentUserServiceImpl.class

@Scope(ScopeConstants.PERTHREAD)
public class CurrentUserServiceImpl implements CurrentUserServiceService {

    private final CrudDAO crudDAO;
    private CurrentUser currentUser;

    public CurrentUserServiceImpl(CrudDAO crudDAO) {
        this.crudDAO = crudDAO;
    }

    public Long getUserId() {
        return getUser().getId();
    }

    public CurrentUser getCurrentUser() {
        if (this.isUserExist() && applicationUser == null) {
            PersonProfile personProfile = (PersonProfile) SecurityUtils.getSubject().getPrincipal();
            currentUser = crudDAO.find(personProfile.getUid());
        }
        return currentUser;
    }

    public boolean isUserExist() {
        return SecurityUtils.getSubject().getPrincipal() != null;
    }
}

PurchaseRequisition.class

public PurchaseRequisition {

    @Inject
    private CurrentUserService currentUserService;

    @Inject
    private CrudDAO crudDAO;

    void setupRender() {
        CurrentUser currentUser = currentUserService.getCurrentUser();

        PurchaseReq pr = crudDAO.find(PurchaseReq.class, id);

        if(currentUser.equals(pr.getAssignedUser()) {
            System.out.println("equal");
        }
    }
}
Code Junkie
  • 7,602
  • 26
  • 79
  • 141
  • 4
    Multiple class loaders. It's pretty nearly impossible to make sense of this from the paucity of information offered here. – bmargulies Dec 27 '13 at 14:15
  • 2
    One could be a subclass of the other. Who creates them? Have you printed them out? Have you printed out the class _names_? – bmargulies Dec 27 '13 at 14:16
  • 1
    Try to debug and see what is returning from both calls to `getClass()`. Hibernate usually creates _proxy_ objects, that is, it dynamically generates subclasses of your entities, so probably the `getClass()` call on your Hibernate object will return the name of the Hibernate-generated class. – drigoangelo Dec 27 '13 at 14:20

2 Answers2

2

Hibernate creates proxy classes using CGLib or javassist. Hence getClass() can't work. Use instanceof instead.

This answer has an alternative solution: https://stackoverflow.com/a/1139992/342852

Community
  • 1
  • 1
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • I'm a little confused, should I be doing something like this in my hash equals? Hibernate.getClass() != obj.getClass() – Code Junkie Dec 27 '13 at 14:39
  • @George as I said, I'd use `instanceof` instead of getClass(). This question discusses the topic in more depth: http://stackoverflow.com/q/596462/342852 – Sean Patrick Floyd Dec 27 '13 at 14:48
1

It can only be when objects classes are loaded with different class loaders:

class TestClassLoader extends URLClassLoader {
...

class Test1 {

    public static void main(String[] args) throws Exception {
        Object obj1 = new TestClassLoader().loadClass("test.Test1").newInstance();
        Object obj2 = new TestClassLoader().loadClass("test.Test1").newInstance();
        System.out.println(obj1.getClass() == obj2.getClass());
    }
}

this will print false

But if obj1 == obj2 then obj1.getClass() == obj2.getClass() always.

Bless
  • 5,052
  • 2
  • 40
  • 44
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275