@JsonIgnore and @JsonBackReference are being Ignored
Asked Answered
G

6

10

I'm working with RestEasy, Jboss 7 and EJB 3.1. I'm creating a RESTful web service that returns data in JSON format.

The problem is that I have a @ManyToOne relationship on one of my entities which causes an infinite recursion during serialization. I tried using Jackson's @JsonIgnore and @JsonBackReference annotations to fix the problem but it seems as if they are being totally ignored and the infinite recursion is still occurring.

This is my User Class:

class User {
    private String userId;
    private Role role;

    @Id
    @Column(name = "\"UserId\"", unique = true, nullable = false, length = 30)
    public String getUserId() {
        return this.UserId;
    }

    public void setUserId(String UserId) {
        this.UserId = UserId;
    }

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "\"RoleId\"", nullable = false)
    //I have tried @JsonIgnore without @JsonBackReference 
    @JsonIgnore
    //I have tried @JsonBackReference without @JsonIgnore 
    //Also I have tried @JsonBackReference and @JsonIgnore together
    @JsonBackReference("role-User")
    public Role getRole() {
        return this.role;
    }
}

This is a part of my Role Class:

@JsonManagedReference("role-User")
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "role")
public Set<User> getUsers() {
    return this.users;
}

I have read somewhere that I should register Jackson with my application to be able to use regular Jaxb annotation so I created a class

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonContextResolver implements ContextResolver<ObjectMapper> {
    public JacksonContextResolver() {
        ObjectMapper mapper = new ObjectMapper();
        AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();

        mapper.getDeserializationConfig().setAnnotationIntrospector(
                introspector);
        mapper.getSerializationConfig().setAnnotationIntrospector(introspector);
    }

    public ObjectMapper getContext(Class<?> objectType) {
        return objectMapper;
    }
}

The problem with the above being that JaxbAnnotationIntrospector() is deprecated.

Please:

  • Do you have any idea why the Jackson annotations are being ignored?
  • How can I use the regular JAXB XML annotations instead of Jackson's?
  • What can I use instead of JaxbAnnotationIntrospector()?

An answer to any of these question is appreciated, thanks.

Update:

For now I have excluded resteasy-jackson-provider using jboss-deployment-structure.xml and I am using Jettison instead. I still want to know how could I use Jackson!

Goal answered 2/6, 2013 at 9:16 Comment(0)
G
12

The problem here seems to be related to using Set<User> instead of List<User>. I had exactly the same problem and changing from Set<User> to List<User> fixed this, otherwise I always got Infinite recursion error from Jackson. I don't know if this is really a bug in Jackson or do you have to provide some other annotations etc. when using Set.

Greyhen answered 27/12, 2013 at 12:15 Comment(0)
P
6

use import com.fasterxml.jackson.annotation.JsonBackReference; instead of import org.codehaus.jackson.annotate.JsonBackReference;.

It was the problem for me.

Phonolite answered 27/3, 2015 at 7:16 Comment(3)
This worked for me (after a few days of struggle). It was necessary after upgrading jackson version. Thank you user104309!Poss
Easy to get caught out - was building against Jackson 1.9, but dev environment has already been upgraded to Jackson 2+, which doesn't know anything about the old annotations.Gibe
Oddly enough, the opposite worked for me, per my own variation of this problem. #35347294. Nonetheless, had I not see this answer, I might have never thought to even check the import. THANK YOU!!!Evasive
P
3

I had this problem and got the same code to work by updating the version of the Jackson library in my build (pom.xml) from 1.8.x to 1.9.13. If you are using maven, edit your pom.xml to contain:

    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.9.13</version>
    </dependency>

Documentation doesn't help, but it seems that back references for Sets were not supported in the 1.8.x versions.

Parada answered 16/10, 2014 at 18:33 Comment(0)
C
2

Look, I have something similar to you and is working just fine for me...

@JsonBackReference("promotion-travel")
@ManyToOne(cascade = CascadeType.ALL)
    @JoinTable(name="PROMOTION_TRAVEL_REL",
        joinColumns = @JoinColumn(name="TRAVEL_ID"),
        inverseJoinColumns = @JoinColumn(name="PROMOTION_ID")
)
public Promotion getPromotion(){...

And this is what I have on Entity1

@JsonManagedReference("promotion-travel")
@OneToMany(mappedBy="promotion")
public List<Travel> getTravelList(){...

I don't know if moving the annotation to the top will change anything, but that's the only thing that I can see...

Cheers,

Crysta answered 17/7, 2013 at 19:36 Comment(0)
S
2

I had a similar problem where my getter function was not named based on the field name, so the json parsing was still happening for the getter. Changing the getter name solved the issue.

Semester answered 11/9, 2020 at 6:9 Comment(0)
F
0

i'm using spring 4.0.1 , hibernate 4.3.5 ,jackson 1.9.2 and STS IDE

i had the same exception but solved by annotating the setter by @Transient idont know why but it works fine

This is my entity classes User.class

    //i get that suggestion from some sites
    @JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
    @Entity
    @Table(name = "user", catalog = "someSchema")    
    public class User implements java.io.Serializable {

        private String name;
        private String password;
        private String username;
        private Set<Telephone> telephones = new HashSet<Telephone>(0);

        @OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
        public Set<Telephone> getTelephones() {
            return this.telephones;
        }

        public void setTelephones(Set<Telephone> telephones) {
            this.telephones = telephones;
        }
    }

Telephone.class

@Entity
@Table(name = "telephone", catalog = "someSchema")
public class Telephone implements java.io.Serializable {


    private User user;
    private String telephone;

    @ManyToOne(fetch = FetchType.LAZY)

    @JoinColumn(name = "user_id", nullable = false)
    public User getUser() {
        return this.user;
    }


    @Transient  
    public void setUser(User user) {
    this.user = user;
   }

}

concerning registering jackson to my application, i used xml config

   <mvc:annotation-driven>
        <mvc:message-converters>
            <bean
                class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean
                        class="web.jsonConverters.HibernateAwareObjectMapper" />
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

and mapper class

public class HibernateAwareObjectMapper extends ObjectMapper {

    public HibernateAwareObjectMapper() {
        Hibernate4Module hm = new Hibernate4Module();
        registerModule(hm);
    }
}
Franciscofranciska answered 29/12, 2014 at 18:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.