Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StackOverflow error on overriding toString() method

Tags:

java

hibernate

I have two classes User & Role. They have a many to many relationship.

In User class I have overridden the toString method

@Override
    public String toString() {
        return "User [userId=" + this.userId + ", profileName=" + this.profileName
                + ", firstName=" + this.firstName + ", lastName=" + this.lastName
                + ", email=" + this.email + ", socialEmail=" + this.socialEmail
                + ", accountEnabled=" + this.accountEnabled + ", accountNonExpired="
                + this.accountNonExpired + ", accountNonLocked=" + this.accountNonLocked
                + ", country=" + this.country + ", role=" + this.role + "]";
    }

Same in Role class

@Override
public String toString() {
    return "Role [roleId=" + roleId + ", users=" + users + ", role=" + role
            + "]";
}

I am fetching the user details from the db by hibernate

@SuppressWarnings("unchecked")
    public User getUser(String name){

        List<User> userList = new ArrayList<User>(); 
        Query query = sessionFactory.getCurrentSession().createQuery("from User u where u.profileName = :name or u.socialEmail = :name");
        query.setParameter("name", name);
        userList = query.list();  
        if (userList.size() > 0)  
            return userList.get(0);  
        else  
            return null; 
    }

When the flow comes to the below line in hibernate method

userList = query.list();

it throws a stack overflow exception showing toString to be the cause can anyone help me with this

java.lang.StackOverflowError
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:113)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:415)
    at java.lang.StringBuilder.append(StringBuilder.java:132)
    at java.lang.StringBuilder.<init>(StringBuilder.java:110)
    at com.myapp.model.User.toString(User.java:189)
    at java.lang.String.valueOf(String.java:2902)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at java.util.AbstractCollection.toString(AbstractCollection.java:450)
    at org.hibernate.collection.PersistentSet.toString(PersistentSet.java:310)
    at java.lang.String.valueOf(String.java:2902)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at com.myapp.model.Role.toString(Role.java:67)

The below line's location is the beginning of toString method in User class

at com.myapp.model.User.toString(User.java:189)
like image 588
underdog Avatar asked Dec 25 '22 17:12

underdog


1 Answers

In the user's toString() you reference role, and in the role's toString() you reference users. Now if each role has a list of users, and each of those user instances have a reference back to the parent role, you have cyclical references. Basically, your object graph looks like this:

Object graph

So what happens is that toString() is called on role, which then tries to call toString() on all users. But it will start with user-1, which has a reference back to role, and the process starts all over again. You essentially have a case of infinite recursion.

like image 178
Vivin Paliath Avatar answered Dec 30 '22 12:12

Vivin Paliath