catnap icon indicating copy to clipboard operation
catnap copied to clipboard

Filtering gets stuck at DefaultModelBuilder throws StackOverflowError

Open miguelsatcom opened this issue 7 years ago • 5 comments

Hello

I'm having some problem while using catnap with Springboot it seems that the DefaultModelBuilder is getting stuck while filtering the object, it goes into an endless loop while and eventually throws an exeption

This is the JSON I get if i make the request without filtering { "status": 200, "result": { "id": 1, "email": "[email protected]", "username": "miguel", "enabled": true, "roles": [ { "createdAt": 1516725487432, "updatedAt": 1516725487432, "id": 3, "name": "ROLE_USER" } ] } }

When trying to get only the result like so curl -X GET 'http://localhost:8081/api/users/1?fields=result'

I get this: { "timestamp": 1516784320900, "status": 500, "error": "Internal Server Error", "exception": "java.lang.StackOverflowError", "message": "No message available", "path": "/api/users/1" }

The Java output are endless lines of this: at com.github.gregwhitaker.catnap.core.model.builder.DefaultModelBuilder.filterObject(DefaultModelBuilder.java:140) ~[catnap-core-2.2.1.jar:na] at com.github.gregwhitaker.catnap.core.model.builder.DefaultModelBuilder.buildObject(DefaultModelBuilder.java:104) ~[catnap-core-2.2.1.jar:na] at com.github.gregwhitaker.catnap.core.model.builder.DefaultModelBuilder.buildList(DefaultModelBuilder.java:70) ~[catnap-core-2.2.1.jar:na] at com.github.gregwhitaker.catnap.core.model.builder.DefaultModelBuilder.filterObject(DefaultModelBuilder.java:140) ~[catnap-core-2.2.1.jar:na]

I also find it interesting that it does work if i for example request the username inside the result like ?fields=result(username)

miguelsatcom avatar Jan 24 '18 09:01 miguelsatcom

Thanks for reporting an issue. I'll take a look at this.

gregwhitaker avatar Jan 25 '18 17:01 gregwhitaker

@miguelsatcom Is there any circular reference in your DTO ? When catnap is enabled by fields query parameter, annotation like @JsonIgnore on field will be ignored. That could be a reason for your problem. I think, there is a circular reference between User class and Role class

Gunju-Ko avatar Feb 20 '18 02:02 Gunju-Ko

@Gunju-Ko I don't think that is the problem. If i make ?fields=result(username) than it works, shouldn't I get the same error if the circular reference was the problem?

miguelsatcom avatar Feb 26 '18 14:02 miguelsatcom

@Gunju-Ko Is it possible to post your DTOs in a gist? It would be helpful to diagnose the issue. The fields in catnap are evaluated lazily so if you have a circular dependency it will only creep up on you and blow up if you happen to select that field.

gregwhitaker avatar Feb 27 '18 17:02 gregwhitaker

@gregwhitaker Hi Please understand that I'm not good at english

Here is example DTOs that caused the stackoverflow bug There is a circular reference between Role and User

    @Data
    public class Member {
        private long id;

        private String email;

        private String userName;

        private boolean enabled;

        private List<Role> roles;
    }
    @Data
    public class Role {
        private long id;

        private Date createdAt;

        private Date updatedAt;

        @JsonIgnore
        private Member member;
    }

If request has a fields parameter and the fields parameter contains roles, than a bug occurs 2018-03-03 12 28 28

Below is a bug message

	at com.github.gregwhitaker.catnap.core.model.builder.DefaultModelBuilder.filterObject(DefaultModelBuilder.java:144)
	at com.github.gregwhitaker.catnap.core.model.builder.DefaultModelBuilder.buildObject(DefaultModelBuilder.java:104)
	at com.github.gregwhitaker.catnap.core.model.builder.DefaultModelBuilder.buildList(DefaultModelBuilder.java:70)
	at com.github.gregwhitaker.catnap.core.model.builder.DefaultModelBuilder.filterObject(DefaultModelBuilder.java:140)
	at com.github.gregwhitaker.catnap.core.model.builder.DefaultModelBuilder.buildObject(DefaultModelBuilder.java:104)

If the fields parameter does not contain roles, or if it is sent without the fields parameter, then problem does not occur.

2018-03-03 12 28 40 2018-03-03 12 28 51

You can solve this problem by adding @JsonIgnore on getter method

    @Data
    public class Role {
        private long id;

        private Date createdAt;

        private Date updatedAt;

        private Member member;

        @JsonIgnore
        public Member getMember() {
            return member;
        }
    }
2018-03-03 12 45 05

I apologize for the lack of explanation because I'm not good at english

Gunju-Ko avatar Mar 03 '18 03:03 Gunju-Ko