No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor
Asked Answered
B

18

141

When i try to navigate to an endpoint i get the following error

Type definition error: [simple type, class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)  

I checked all my models and all the attributes have getters and setters. So what's the problem ?

I can fix that by adding spring.jackson.serialization.fail-on-empty-beans=false but i think this is just a work around to hide the exception.

Edit

Product model:

@Entity
public class Product {
    private int id;
    private String name;
    private String photo;
    private double price;
    private int quantity;
    private Double rating;
    private Provider provider;
    private String description;
    private List<Category> categories = new ArrayList<>();
    private List<Photo> photos = new ArrayList<>();
    
    // Getters & Setters
}

PagedResponse class :

public class PagedResponse<T> {

    private List<T> content;
    private int page;
    private int size;
    private long totalElements;
    private int totalPages;
    private boolean last;
    
    // Getters & Setters
}

RestResponse Class :

public class RestResponse<T> {
    private String status;
    private int code;
    private String message;
    private T result;

    // Getters & Setters
}

In my controller i'm returning ResponseEntity<RestResponse<PagedResponse<Product>>>

Betti answered 4/10, 2018 at 23:49 Comment(5)
I faced the same exact issue, added the prop entry and I'm able to see the response, previously it was failing. Thanks for this questions and the hint fail-on-empty-beansCarbon
check the answer here https://mcmap.net/q/161571/-how-to-serialize-a-json-containing-lazy-associationsSamson
spring.jackson.serialization.fail-on-empty-beans=false solves for me too. but i dont know what is error onFlaminius
In my case I was using groovy / grails and wasn't working as response wasn't in the JSON format. Added return result as JSON and it worked.Game
Me too. Thanks. But i do not know what is error.Missymist
K
215

I came across this error while doing a tutorial with spring repository. It turned out that the error was made at the stage of building the service class for my entity.

In your serviceImpl class, you probably have something like:

    @Override
    public YourEntityClass findYourEntityClassById(Long id) {
      return YourEntityClassRepositorie.getOne(id);
    }

Change this to:

    @Override
    public YourEntityClass findYourEntityClassById(Long id) {
      return YourEntityClassRepositorie.findById(id).get();
    }

Basically getOne is a lazy load operation. Thus you get only a reference (a proxy) to the entity. That means no DB access is actually made. Only when you call it's properties then it will query the DB. findByID does the call 'eagerly'/immediately when you call it, thus you have the actual entity fully populated.

Take a look at this: Link to the difference between getOne & findByID

Keverne answered 21/10, 2019 at 16:47 Comment(6)
@Keverne thanks for this, i was getting the same error cause i was using getOne() method now changed it to findById(id).get().Lamprey
wow, @Szelek, You are god. I don't understand why this little change saved my life.Lennon
Fixed for me, thanks for the info. Watched a tutorial where they used getOne(), anyone know why that method is not working properly?Beeline
@LayLeangsros wondered the same thing my self. Found this great article which describes the differences between the getOne and findById. Basically getOne is a lazy load operation. Thus you get only a reference (a proxy) to the entity. That means no DB access is actually made. Only when you call it's properties then it will query the DB. findByID does the call eagry right when you call it, thus you have the actual entity fully populated. javacodemonk.com/…Obovate
Any future people to run into this problem remember there are two methods findById and getById. findById returns an optional that's why you have to do a .get at the end of the method call. Change it to findById and you will be fine.Butacaine
Why does this error occur though? There seems to be a bigger issue if getById is not workingZigrang
S
140

You can Ignore to produce JSON output of a property by

@JsonIgnore 

Or If you have any lazy loaded properties having a relationship. You can use this annotation at top of the property.

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

Example:

@Entity
public class Product implements Serializable{
   private int id;
   private String name;
   private String photo;
   private double price;
   private int quantity;
   private Double rating;
   private Provider provider;
   private String description;

   @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
   private List<Category> categories = new ArrayList<>();

   @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
   private List<Photo> photos = new ArrayList<>();

   // Getters & Setters
}

If you still have this error, please add this line of code in your application.properties file

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

I hope your problem will be solved. Thanks.

Sri answered 29/1, 2019 at 6:42 Comment(11)
The solution provided with "@JsonIgnoreProperties" did not work for me. Changing from FetchType.LAZY to FetchType.EAGER fixed the issue.Woolly
@Subarata Talukder - If we use @JsonIgnore, then we loose the entity graph details as well..Beguin
@Woolly - I'm also getting same error, but in my case, I can't keep doing FetchType.EAGER. Could you please help me with this ?Beguin
I'd wonder why anyone would use Serializable interface anymore. Is that a Hibernate requirement?Gyrus
@PAA sorry for the delay. Not sure if still in time, but I suggest you to take a look at baeldung.com/hibernate-lazy-eager-loading to double check if you are using lazy loading the right way. As explained in "5. Differences", I guess that in my case the exception occurred due to missing call of getter, which triggers the fetch, initializing all attributes of a given object. Alternative to that, there is a way to use a proxy, also explained in this same post. I will soon leave eager and go back to lazy, as eager is a bad practice.Woolly
Please add this line in your application.properties file spring.jackson.serialization.fail-on-empty-beans=false, if you have still this issue.Sri
spring.jackson.serialization.fail-on-empty-beans=false, worked for me Thanks :)Maze
But this is not an answer to the questionKirstiekirstin
Pls let the answer of the question @ACV.Sri
Adding spring.jackson.serialization.fail-on-empty-beans=false in my properties file solved it for meDitchwater
spring.jackson.serialization.fail-on-empty-beans=false Does not work in Spring Boot 2.2.5 and above. Also the properties need to be Public in order for it to work.Kussell
C
25

Changing the FetchType from Lazy to Eager did the trick for me.

Chromous answered 20/3, 2020 at 11:11 Comment(2)
This approach is not the right solution. As this disables the LAZY mode resulting in many unnecessary queries for data you probably won't require.Kaylyn
@Kaylyn this good answer given you want to query products with its Categories @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "categoryId") private Category category;Hob
H
17

This answer comes from the book: "learn microservices with spring boot" Instead of supressing the error on empty bean which is suggested by the spring there are more preferable ways to handle this.

We configured our nested User entities to be fetched in LAZY mode, so they’re not being queried from the database. We also said that Hibernate creates proxies for our classes in runtime. That’s the reason behind the ByteBuddyInterceptor class. You can try switching the fetch mode to EAGER, and you will no longer get this error. But that’s not the proper solution to this problem since then we’ll be triggering many queries for data we don’t need. Let’s keep the lazy fetch mode and fix this accordingly. The first option we have is to customize our JSON serialization so it can handle Hibernate objects. Luckily, FasterXML,the provider of Jackson libraries, has a specific module for Hibernate that we can use in our ObjectMapper objects: jackson-datatype-hibernate:

<dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-hibernate5</artifactId>
</dependency>

We create a bean for our new Hibernate module for Jackson. Spring Boot’s Jackson2ObjectMapperBuilder will use it via autoconfiguration, and all our ObjectMapper instances will use the Spring Boot defaults plus our own customization.

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 JsonConfiguration {
    @Bean
    public Module hibernateModule() {
        return new Hibernate5Module();
    }
}
Haplology answered 9/3, 2022 at 22:22 Comment(2)
See my response https://mcmap.net/q/159440/-no-serializer-found-for-class-org-hibernate-proxy-pojo-bytebuddy-bytebuddyinterceptor for how to do this using jakarta.* libraries.Kaylyn
That's amazing! The other solutions work, but this should be the top answer :)Runion
P
15

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) work for me very well. It doesn't miss any reference objects and resolve the problem.

In my case:

@Entity
@Table(name = "applications")
public class Application implements Serializable {

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

    @NotBlank
    @Size(max = 36, min = 36)
    private String guid;

    @NotBlank
    @Size(max = 60)
    private String name;

    @Column(name = "refresh_delay")
    private int refreshDelay;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "id_production", referencedColumnName = "id")
    @JsonIgnoreProperties(value = {"applications", "hibernateLazyInitializer"})
    private Production production;
Preservative answered 15/8, 2020 at 18:1 Comment(0)
B
8

This solved my issue.

 @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
Blench answered 10/2, 2021 at 0:30 Comment(1)
Please add some documentation on where the parameters "handler" and "hibernateLazyInitializer" come from.Cambrai
P
4

Changing from

MyEntityClassRepositorie.getOne(id)

to

MyEntityClassRepositorie.findById(id).get()

work fine for me.

Platinumblond answered 29/11, 2020 at 1:35 Comment(2)
I changed from getById(id) to findById(id).getSaundrasaunter
It Worked for me. Error gone after this. Thank you! @GeogesGavingavini
K
3

i also faced same problem. I was using repo.getOne(id); i changed it to repo.findById(id). It returned optional, but now error is gone

Kroo answered 28/9, 2020 at 12:12 Comment(0)
F
3

If you are using spring 6 then it will work

spring:
  jackson:
    serialization:
      fail-on-empty-beans: false
Fling answered 15/2, 2023 at 5:44 Comment(1)
This approach has more overhead, see my resolution using JsonConfiguration below for a better solution to this problem.Kaylyn
K
3

Add the following dependency in your pom.xml for javax.*

<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>

Or following for jakarta.*

<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5-jakarta</artifactId>

And add the configuration as below for javax.*:

package microservices.book.multiplication.configuration;

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

@Configuration
public class JsonConfiguration {
    @Bean
    public Module hibernateModule() {
        return new Hibernate5JakartaModule();
    }
   
}

Or for jakarta.* package, add the configuration as below:

package microservices.book.multiplication.configuration;

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

@Configuration
public class JsonConfiguration {
    @Bean
    public Module hibernateModule() {
        return new Hibernate5JakartaModule();
    }
   
}

The above two steps should resolve this issue.

Kaylyn answered 29/6, 2023 at 17:0 Comment(1)
I was hitting this with some of my POJOs but not others. This fix worked for me. Thank you.Malorie
M
2

I also faced with this problem. @Szelek's answer helped me. But I did it with another way. Changed getOne() method to:

repository.findById(id).orElse(null)

Ensure you are taking care of the NullPointerException this will generate when it's not found.

Moll answered 13/12, 2019 at 19:55 Comment(3)
This will throw a NullPointer Exception. Optional cannot return nullSinistrorse
Thank you. You saved my day.Watercool
@Sinistrorse About Optional: A container object which may or may not contain a non-null value.Moll
L
0

For me, I got this error for a DTO object. The problem was I didn't provide getters for DTO properties. Therefore, Jackson was not able to fetch those values and assumed the bean is empty. Solution:

Add Getters to your DTO

Lid answered 9/2, 2021 at 8:7 Comment(0)
G
0

In my case I was facing same exception with @EntityGraph. Actually I was trying to fetch OneToMany (inventoryList) via EntityGraph and it's working but when I tried get another relation with ManyToOne (category) it was giving error. I don't know why it became lazy. As we know @ManyToOne is by default eager.

class Product {
 
    @ManyToOne
    @JoinColumn(name = "categoryId")
    private Category category;

    @OneToMany(mappedBy = "product", cascade = CascadeType.ALL)
    private List<Inventory> inventoryList;
}

Repository method:

@EntityGraph(attributePaths = { "inventoryList" })
List<Product> findAll();

I was getting same expection because I didn't add category in EntityGraph fetch. After adding category it's get fixed.

@EntityGraph(attributePaths = { "inventoryList", "category" })
List<Product> findAll();
Gnatcatcher answered 26/4, 2022 at 17:46 Comment(0)
M
0

I faced this problem once I moved to using jakarta.persistence library , once I changed back to javax.persistence the problem sovled.

Mcripley answered 9/2, 2023 at 16:17 Comment(2)
See my comment above, change your javax.* configuration to jakarta.* configuration to resolve this issue without reverting back to older javax.* libraries.Kaylyn
Here is the link for your easy reference https://mcmap.net/q/159440/-no-serializer-found-for-class-org-hibernate-proxy-pojo-bytebuddy-bytebuddyinterceptorKaylyn
A
0

My approach was just use findById() with orElseThrow() method instead of getReferenceById().

I ended up like this:

  @PutMapping("/{id}")
    public Food updateFood(
            @PathVariable("id") Long id,
            @RequestBody
            @Validated RequestUpdateFoodDTO data
    ){
        Food food = this.repository.findById(id).orElseThrow();
        
        food.setTitle(data.title());
        food.setImage(data.image());
        food.setPrice(data.price());

        repository.save(food);

        return food;
    }
Arnaud answered 5/2 at 13:36 Comment(0)
F
-1

Hmm are you traying to send entities from one instance of the jvm to another one which need to serialize them? if this is the case i think the error is because you fetched the entities somehow and hibernate is using its not serializable classes, you need to convert entities to pojo's (i mean use native types or objects that are serializables).

Friendship answered 5/10, 2018 at 1:44 Comment(1)
I don't understand exactly what you're saying but I think I'm doing that, please check my edit.Betti
B
-1

i found the approach from other article, you can add the public setter and getter in your class, it can solve this problem

Ballon answered 26/7, 2023 at 16:15 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Pictorial
S
-2

As I worked on localhost I just needed a Server. The following worked for me

<dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-jasper</artifactId>
        <version>9.0.65</version>
</dependency>
Schluter answered 31/7, 2022 at 18:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.