Reputation: 374
I'm trying to configure mongodb auditing in my spring boot app, and I having this error when trying to persist my domain class:
java.lang.IllegalArgumentException: Couldn't find PersistentEntity for type class com.example.hateoasapi.domain.Post!
Docs from here https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#auditing says that all this configs enough, but I don't know why it doesn't work in my project. Could someone help me?
My mongodb config class:
package com.example.hateoasapi.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.config.EnableMongoAuditing;
import org.springframework.data.mongodb.core.MongoTemplate;
import com.mongodb.MongoClient;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import java.util.Collection;
import java.util.Collections;
@Configuration
@EnableMongoAuditing
@EnableMongoRepositories(value = "com.example.hateoasapi.repository")
public class MongoConfig extends AbstractMongoConfiguration {
@Value("${spring.data.mongodb.database}")
private String databaseName;
@Value("${spring.data.mongodb.host}")
private String databaseHost;
@Value("${spring.data.mongodb.port}")
private Integer databasePort;
@Override
protected String getDatabaseName() {
return this.databaseName;
}
@Bean
@Override
public MongoClient mongoClient() {
return new MongoClient(databaseHost, databasePort);
}
@Bean
public MongoTemplate mongoTemplate() {
return new MongoTemplate(mongoClient(), databaseName);
}
@Override
protected Collection<String> getMappingBasePackages() {
return Collections.singleton("com.example.hateoasapi.domain");
}
}
AuditorAware implementation:
package com.example.hateoasapi.config;
import com.example.hateoasapi.domain.User;
import org.springframework.data.domain.AuditorAware;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class SecurityAuditor implements AuditorAware<User> {
@Override
public Optional<User> getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return null;
}
return Optional.of((User) authentication.getPrincipal());
}
}
And my domain class:
package com.example.hateoasapi.domain;
import javax.persistence.Id;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import org.joda.time.DateTime;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.hateoas.ResourceSupport;
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
import java.io.Serializable;
import java.util.List;
import com.example.hateoasapi.controller.*;
@Getter
@Setter
@ToString
@Document
public class Post extends ResourceSupport implements Serializable {
@Id
@Field(value = "_id")
private String objectId;
@DBRef
private List<Comment> comments;
@DBRef
private User author;
@NotBlank
private String body;
@NotBlank
private String title;
private String categoryId;
@NotEmpty(message = "Tags cannot be empty")
private List<PostTag> tags;
@CreatedDate
private DateTime createdDate;
@LastModifiedDate
private DateTime lastModifiedDate;
@CreatedBy
private User createdBy;
private Long views;
private List<PostRating> likes;
private List<PostRating> dislikes;
@JsonCreator
public Post() {}
public Post(String title, String body) {
this.body = body;
this.title = title;
}
public Post(User author, String body, String title, String categoryId, List<PostTag> tags) {
this.author = author;
this.body = body;
this.title = title;
this.categoryId = categoryId;
this.tags = tags;
}
public void addLinks() {
this.add(linkTo(methodOn(PostController.class).getAllPosts(null)).withSelfRel());
}
}
Upvotes: 5
Views: 6364
Reputation: 1
I had this problem also with spring boot 2.2
I had both @EnableMongoRepositories
and @EnableMongoAuditing
as configuration and i got the error Couldn't find PersistentEntity for type class
the problem in my case was the structure of the packages: Application class was a level lower than part of my model that used auditing.
I found on many forum posts that the 2 annotations are not compatible together in spring 2.2, but after restructuring the packages I was able to use both with success in spring boot 2.2
Upvotes: 0
Reputation: 95
I solved this issue with the next configuration:
@Configuration
@EnableMongoRepositories(basePackages = "YOUR.PACKAGE")
@EnableMongoAuditing
public class MongoConfig extends AbstractMongoConfiguration {
@Value("${spring.data.mongodb.host}")
private String host;
@Value("${spring.data.mongodb.port}")
private Integer port;
@Value("${spring.data.mongodb.database}")
private String database;
@Override
public MongoClient mongoClient() {
return new MongoClient(host, port);
}
@Override
protected String getDatabaseName() {
return database;
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
}
@Bean
public MongoDbFactory mongoDbFactory() {
return new SimpleMongoDbFactory(mongoClient(), database);
}
}
just add the bean for MongoTemplate
with the constructor of MongoTemplate(MongoDbFactory mongoDbFactory, @Nullable MongoConverter mongoConverter)
Upvotes: 3
Reputation: 14303
Quoting from JIRA ticket
You need to pipe the MappingMongoConverter that's available in the environment into MongoTemplate as well, i.e. use new MongoTemplate(dbFactory, converter). The constructor you use is for convenience, one-off usages. We usually recommend to use AbstractMongoConfiguration in case you'd like to customize anything MongoDB specific as this makes sure the components are wired together correctly.
More specifically, you need to inject pre-configured MappingMongoConverter or if you need to use your own converter, at least use pre-configured MongoMappingContext.
Upvotes: 1
Reputation: 124
If you use the last version of Spring boot (2.0) and Spring Data, @EnableMongoAuditing and @EnableMongoRepositories, try remove @EnableMongoRepositories. It should be working just this sample project - https://github.com/hantsy/spring-reactive-sample/tree/master/boot-data-mongo
Upvotes: -1
Reputation: 1
If you use the last version of Spring boot (2.0) and Spring Data, @EnableMongoAuditing @EnableMongoRepositories are not compatible. It's the same with EnableReactiveMongoRepositories annotation.
If you want to enable mongo auditing, you need to remove your MongoConfig class, use config file to define your mongodb connection and everything will work.
Upvotes: -1