No serializer found for class org.hibernate.proxy.pojo.javassist.Javassist?

JsonSpringHibernate

Json Problem Overview


I am working on SpringMVC, Hibernate & JSON but I am getting this error.

HTTP Status 500 - Could not write JSON: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.SerializationFeature.FAIL_ON_EMPTY_BEANS) ) 

Please check my Entity below

    @Entity
@Table(name="USERS")
public class User {
	
	@Id
	@GeneratedValue
	@Column(name="USER_ID")
	private Integer userId;
	
	@Column(name="USER_FIRST_NAME")
	private String firstName;
	
	@Column(name="USER_LAST_NAME")
	private String lastName;
	

	@Column(name="USER_MIDDLE_NAME")
	private String middleName;
	
	@Column(name="USER_EMAIL_ID")
	private String emailId;
	
	@Column(name="USER_PHONE_NO")
	private Integer phoneNo;
	
	@Column(name="USER_PASSWORD")
	private String password;
	
	@Column(name="USER_CONF_PASSWORD")
	private String  confPassword;
	
	@Transient
	private String token;
	
	@Column(name="USER_CREATED_ON")
	private Date createdOn;
	
	@OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
	@Fetch(value = FetchMode.SUBSELECT)
	@JoinTable(name = "USER_ROLES", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
	private List<ActifioRoles> userRole = new ArrayList<ActifioRoles>();
	
	
	@OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL,mappedBy="userDetails")
	@Fetch(value = FetchMode.SUBSELECT)
	private List<com.actifio.domain.Address> userAddress = new ArrayList<com.actifio.domain.Address>();
	
	@OneToOne(cascade=CascadeType.ALL)
	private Tenant tenantDetails;
	
	
	public Integer getUserId() {
		return userId;
	}
	public void setUserId(Integer userId) {
		this.userId = userId;
	}
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getEmailId() {
		return emailId;
	}
	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getConfPassword() {
		return confPassword;
	}
	public void setConfPassword(String confPassword) {
		this.confPassword = confPassword;
	}
	public Date getCreatedOn() {
		return createdOn;
	}
	public void setCreatedOn(Date createdOn) {
		this.createdOn = createdOn;
	}
	
	public List<ActifioRoles> getUserRole() {
		return userRole;
	}
	
	public void setUserRole(List<ActifioRoles> userRole) {
		this.userRole = userRole;
	}
	public String getMiddleName() {
		return middleName;
	}
	public void setMiddleName(String middleName) {
		this.middleName = middleName;
	}
	public Integer getPhoneNo() {
		return phoneNo;
	}
	public void setPhoneNo(Integer phoneNo) {
		this.phoneNo = phoneNo;
	}
	
	public List<com.actifio.domain.Address> getUserAddress() {
		return userAddress;
	}
	public void setUserAddress(List<com.actifio.domain.Address> userAddress) {
		this.userAddress = userAddress;
	}
	public Tenant getTenantDetails() {
		return tenantDetails;
	}
	public void setTenantDetails(Tenant tenantDetails) {
		this.tenantDetails = tenantDetails;
	}
	public String getToken() {
		return token;
	}
	public void setToken(String token) {
		this.token = token;
	}
    
    }

How can I Solve this?

Json Solutions


Solution 1 - Json

I had a similar problem with lazy loading via the hibernate proxy object. Got around it by annotating the class having lazy loaded private properties with:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

I assume you can add the properties on your proxy object that breaks the JSON serialization to that annotation.

The problem is that entities are loaded lazily and serialization happens before they get loaded fully.

Hibernate.initialize(<your getter method>);

Solution 2 - Json

Just to add this in, I ran into this same issue, but the supplied answers did not work. I fixed it by taking the exception's suggestion and adding to the application.properties file...

spring.jackson.serialization.fail-on-empty-beans=false

I'm using Spring Boot v1.3 with Hibernate 4.3

It now serializes the entire object and nested objects.

EDIT: 2018

Since this still gets comments I'll clarify here. This absolutely only hides the error. The performance implications are there. At the time, I needed something to deliver and work on it later (which I did via not using spring anymore). So yes, listen to someone else if you really want to solve the issue. If you just want it gone for now go ahead and use this answer. It's a terrible idea, but heck, might work for you. For the record, never had a crash or issue again after this. But it is probably the source of what ended up being a SQL performance nightmare.

Solution 3 - Json

As it is correctly suggested in previous answers, lazy loading means that when you fetch your object from the database, the nested objects are not fetched (and may be fetched later when required).

Now Jackson tries to serialize the nested object (== make JSON out of it), but fails as it finds JavassistLazyInitializer instead of normal object. This is the error you see. Now, how to solve it?

As suggested by CP510 previously, one option is to suppress the error by this line of configuration:

spring.jackson.serialization.fail-on-empty-beans=false

But this is dealing with the symptoms, not the cause. To solve it elegantly, you need to decide whether you need this object in JSON or not?

  1. Should you need the object in JSON, remove the FetchType.LAZY option from the field that causes it (it might also be a field in some nested object, not only in the root entity you are fetching).

  2. If do not need the object in JSON, annotate the getter of this field (or the field itself, if you do not need to accept incoming values either) with @JsonIgnore, for example:

    // this field will not be serialized to/from JSON @JsonIgnore private NestedType secret;

Should you have more complex needs (e.g. different rules for different REST controllers using the same entity), you can use jackson views or filtering or for very simple use case, fetch nested objects separately.

Solution 4 - Json

You could use the add-on module for Jackson which handles Hibernate lazy-loading.

More info on https://github.com/FasterXML/jackson-datatype-hibernate wich support hibernate 3 and 4 separately.

Solution 5 - Json

I think that the problem is the way that you retrieve the entity.

Maybe you are doing something like this:

Person p = (Person) session.load(Person.class, new Integer(id));

Try using the method get instead of load

Person p = (Person) session.get(Person.class, new Integer(id));

The problem is that with load method you get just a proxy but not the real object. The proxy object doesn't have the properties already loaded so when the serialization happens there are no properties to be serialized. With the get method you actually get the real object, this object could in fact be serialized.

Solution 6 - Json

it works for me

@JsonIgnoreProperties({"hibernateLazyInitializer","handler"})

e.g.

@Entity
@Table(name = "user")
@Data
@NoArgsConstructor
@JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private Date created;

}

Solution 7 - Json

There are two ways to fix the problem.

Way 1:

Add spring.jackson.serialization.fail-on-empty-beans=false into application.properties

Way 2:

Use join fetch in JPQL query to retrieve parent object data, see below:

@Query(value = "select child from Child child join fetch child.parent Parent ",
           countQuery = "select count(*) from Child child join child.parent parent ")
public Page<Parent> findAll(Pageable pageable); 

Solution 8 - Json

Add this Annotation to Entity Class (Model) that works for me this cause lazy loading via the hibernate proxy object.

> @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

Solution 9 - Json

This Exception >org.springframework.http.converter.HttpMessageNotWritableException

getting because, I hope so, your are sending response output as Serializable object.
This is problem occurring in spring. To over come this issue, send POJO object as response output.

Example :

    @Entity
    @Table(name="user_details")
    public class User implements Serializable{
    
        @Id
    	@GeneratedValue(strategy= GenerationType.IDENTITY)
    	@Column(name="id")
    	private Integer id;
    
    	@Column(name="user_name")
    	private String userName;
    	
    	@Column(name="email_id")
    	private String emailId;
    	
    	@Column(name="phone_no")
    	private String phone;

//setter and getters

POJO class:

public class UserVO {
	
	private int Id;
	private String userName;
	private String emailId;
	private String phone;
	private Integer active;
	
//setter and getters

In controller convert the serilizable object fields to POJO class fields and return pojo class as output.

         User u= userService.getdetials(); // get data from database

		UserVO userVo= new UserVO();  // created pojo class object

		userVo.setId(u.getId());
		userVo.setEmailId(u.getEmailId());
		userVo.setActive(u.getActive());
		userVo.setPhone(u.getPhone());
		userVo.setUserName(u.getUserName());
       retunr userVo;  //finally send pojo object as output.

Solution 10 - Json

In the Hibernate 5.2 and above, you able to remove the hibernate proxy as below, it will give you the actual object so you can serialize it properly:

Object unproxiedEntity = Hibernate.unproxy( proxy );

Solution 11 - Json

For Hibernate you can use the jackson-datatype-hibernate project to accommodate JSON serialization/deserialization with lazy-loaded objects.

For example,

import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonDatatypeHibernate5Configuration {

    // Register Jackson Hibernate5 Module to handle JSON serialization of lazy-loaded entities
    // Any beans of type com.fasterxml.jackson.databind.Module are automatically
    // registered with the auto-configured Jackson2ObjectMapperBuilder
    // https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper
    @Bean
    public Module hibernate5Module() {
        Hibernate5Module hibernate5Module = new Hibernate5Module();
        hibernate5Module.enable( Hibernate5Module.Feature.FORCE_LAZY_LOADING );
        hibernate5Module.disable( Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION );
        return hibernate5Module;
    }
}

Solution 12 - Json

The solution is inspired from the below solution by @marco. I have also updated his answer with these datails.

The problem here is about lazy loading of the sub-objects, where Jackson only finds hibernate proxies, instead of full blown objects.

So we are left with two options - Suppress the exception, like done above in most voted answer here, or make sure that the LazyLoad objects are loaded.

If you choose to go with latter option, solution would be to use jackson-datatype library, and configure the library to initialize lazy-load dependencies prior to the serialization.

I added a new config class to do that.

@Configuration
public class JacksonConfig extends WebMvcConfigurerAdapter {

@Bean
@Primary
public MappingJackson2HttpMessageConverter jacksonMessageConverter(){
    MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper mapper = new ObjectMapper();
    Hibernate5Module module = new Hibernate5Module();
    module.enable(Hibernate5Module.Feature.FORCE_LAZY_LOADING);
    mapper.registerModule(module);
    messageConverter.setObjectMapper(mapper);
    return messageConverter;
}

}

@Primary makes sure that no other Jackson config is used for initializing any other beans. @Bean is as usual. module.enable(Hibernate5Module.Feature.FORCE_LAZY_LOADING); is to enable Lazy loading of the dependencies.

Caution - Please watch for its performance impact. sometimes EAGER fetch helps, but even if you make it eager, you are still going to need this code, because proxy objects still exist for all other Mappings except @OneToOne

PS : As a general comment, I would discourage the practice of sending whole data object back in the Json response, One should be using Dto's for this communication, and use some mapper like mapstruct to map them. This saves you from accidental security loopholes, as well as above exception.

Solution 13 - Json

I've the same problem right now. check if you fix fetch in lazy with a @jsonIQgnore

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="teachers")
@JsonIgnoreProperties("course")
Teacher teach;

Just delete the "(fetch=...)" or the annotation "@jsonIgnore" and it will work

@ManyToOne
@JoinColumn(name="teachers")
@JsonIgnoreProperties("course")
Teacher teach;

Solution 14 - Json

Or you could configure mapper as :

// custom configuration for lazy loading

public static class HibernateLazyInitializerSerializer extends JsonSerializer<JavassistLazyInitializer> {

    @Override
    public void serialize(JavassistLazyInitializer initializer, JsonGenerator jsonGenerator,
            SerializerProvider serializerProvider)
            throws IOException, JsonProcessingException {
        jsonGenerator.writeNull();
    }
}

and configure mapper:

    mapper = new JacksonMapper();
    SimpleModule simpleModule = new SimpleModule(
            "SimpleModule", new Version(1,0,0,null)
    );
    simpleModule.addSerializer(
            JavassistLazyInitializer.class,
            new HibernateLazyInitializerSerializer()
    );
    mapper.registerModule(simpleModule);

Solution 15 - Json

It could be your Hibernate entity relationship causing the issue...simply stop lazy loading of that related entity...for example...I resolved below by setting lazy="false" for customerType.

<class name="Customer" table="CUSTOMER">
		<id name="custId" type="long">
			<column name="CUSTID" />
			<generator class="assigned" />
		</id>
		<property name="name" type="java.lang.String">
			<column name="NAME" />
		</property>
		<property name="phone" type="java.lang.String">
			<column name="PHONE" />
		</property>
		<property name="pan" type="java.lang.String">
			<column name="PAN" />
		</property>

		<many-to-one name="customerType" not-null="true" lazy="false"></many-to-one>
	</class>
</hibernate-mapping>

Solution 16 - Json

I changed (in Annotation model class)

> fetch = FetchType.LAZY

to

> fetch = FetchType.EAGER

and worked in pretty way...

Love it.

Solution 17 - Json

This is an issue with Jackson. To prevent this, instruct Jackson not to serialize nested relationship or nested class.

Look at the following example. Address class mapped to City, State, and Country classes and the State itself is pointing to Country and Country pointing to Region. When your get address values through Spring boot REST API you will get the above error. To prevent it, just serialize mapped class ( which reflects level one JSON) and ignore nested relationships with @JsonIgnoreProperties(value = {"state"}),@JsonIgnoreProperties(value = {"country"}) and @JsonIgnoreProperties(value = {"region"})

This will prevent Lazyload exception along with the above error. Use the below code as an example and change your model classes.

Address.java

@Entity
public class Address extends AbstractAuditingEntity
{
    private static final long serialVersionUID = 4203344613880544060L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "street_name")
    private String streetName;

    @Column(name = "apartment")
    private String apartment;

    @ManyToOne
    @JoinColumn(name = "city_id")
    @JsonIgnoreProperties(value = {"state"})
    private City city;

    @ManyToOne
    @JoinColumn(name = "state_id")
    @JsonIgnoreProperties(value = {"country"})
    private State state;

    @ManyToOne
    @JoinColumn(name = "country_id")
    @JsonIgnoreProperties(value = {"region"})
    private Country country;

    @ManyToOne
    @JoinColumn(name = "region_id")
    private Region region;

    @Column(name = "zip_code")
    private String zipCode;

    @ManyToOne
    @JoinColumn(name = "address_type_id", referencedColumnName = "id")
    private AddressType addressType;

}

City.java

@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "city")
@Cache(region = "cityCache",usage = CacheConcurrencyStrategy.READ_WRITE)
@Data
public class City extends AbstractAuditingEntity
{
    private static final long serialVersionUID = -8825045541258851493L;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    //@Length(max = 100,min = 2)
    private String name;


    @ManyToOne
    @JoinColumn(name = "state_id")
    private State state;
}

State.java

@Entity
@Table(name = "state")
@Data
@EqualsAndHashCode(callSuper = true)
public class State extends AbstractAuditingEntity
{
    private static final long serialVersionUID = 5553856435782266275L;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "code")
    private String code;

    @Column(name = "name")
    @Length(max = 200, min = 2)
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "country_id")
    private Country country;

}

Country.java

@Entity
@Table(name = "country")
@Data
@EqualsAndHashCode(callSuper = true)
public class Country extends AbstractAuditingEntity
{
    private static final long serialVersionUID = 6396100319470393108L;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    @Length(max = 200, min = 2)
    private String name;

    @Column(name = "code")
    @Length(max = 3, min = 2)
    private String code;

    @Column(name = "iso_code")
    @Length(max = 3, min = 2)
    private String isoCode;

    @ManyToOne
    @JoinColumn(name = "region_id")
    private Region region;
}

Solution 18 - Json

@JsonIgnoreProperties({"hibernateLazyInitializer","handler"})

it works for me

Solution 19 - Json

Try

implements interface Serializable

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2963481View Question on Stackoverflow
Solution 1 - JsonAnkur SinghalView Answer on Stackoverflow
Solution 2 - JsonCP510View Answer on Stackoverflow
Solution 3 - JsonMF.OXView Answer on Stackoverflow
Solution 4 - JsonMarco AndreiniView Answer on Stackoverflow
Solution 5 - JsonCarlos ZegarraView Answer on Stackoverflow
Solution 6 - JsonGiraffeTreeView Answer on Stackoverflow
Solution 7 - JsonfangtingView Answer on Stackoverflow
Solution 8 - JsonAkitha_MJView Answer on Stackoverflow
Solution 9 - JsonSai GoudView Answer on Stackoverflow
Solution 10 - JsonSam YCView Answer on Stackoverflow
Solution 11 - JsonPhilip WrageView Answer on Stackoverflow
Solution 12 - JsonAnand VaidyaView Answer on Stackoverflow
Solution 13 - JsonAminozView Answer on Stackoverflow
Solution 14 - JsonahllView Answer on Stackoverflow
Solution 15 - JsonbjethwanView Answer on Stackoverflow
Solution 16 - JsonSham FiorinView Answer on Stackoverflow
Solution 17 - JsonPavan JaddaView Answer on Stackoverflow
Solution 18 - JsonAnkush SupnarView Answer on Stackoverflow
Solution 19 - JsonborinoView Answer on Stackoverflow