Reputation: 8868
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>>>
Upvotes: 151
Views: 199547
Reputation: 523
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;
}
Upvotes: 0
Reputation: 1
i found the approach from other article, you can add the public setter and getter in your class, it can solve this problem
Upvotes: -1
Reputation: 838
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.
Upvotes: 4
Reputation: 119
If you are using spring 6 then it will work
spring:
jackson:
serialization:
fail-on-empty-beans: false
Upvotes: 5
Reputation: 1387
I faced this problem once I moved to using jakarta.persistence
library , once I changed back to javax.persistence
the problem sovled.
Upvotes: 0
Reputation: 2424
Changing the FetchType
from Lazy
to Eager
did the trick for me.
Upvotes: 29
Reputation: 52
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>
Upvotes: -2
Reputation: 1106
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();
Upvotes: 0
Reputation: 338
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();
}
}
Upvotes: 20
Reputation: 41
Changing from
MyEntityClassRepositorie.getOne(id)
to
MyEntityClassRepositorie.findById(id).get()
work fine for me.
Upvotes: 4
Reputation: 91
This solved my issue.
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
Upvotes: 9
Reputation: 10675
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
Upvotes: 0
Reputation: 69
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.
Upvotes: 2
Reputation: 2837
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
Upvotes: 220
Reputation: 92
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
Upvotes: 3
Reputation: 719
@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;
Upvotes: 15
Reputation: 6311
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.
Upvotes: 142
Reputation: 355
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).
Upvotes: -1