'Couldn't find PersistentEntity for type class' exception in Spring boot MongoRepository - spring-boot

In here I have configured two databases in mongodb. As described in this tutorial (link). So basically I override the MongoDataAutoConfiguration and MongoProperties implementations.
The property yml file :
spring:
autoconfigure:
exclude:
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration
mongodb:
primary:
host: 127.0.0.1
port: 27017
database: db_admin_crm
secondary:
host: 127.0.0.1
port: 27017
database: lead_forms
MultipleMongoProperties class :
#Data
#ConfigurationProperties(prefix = "mongodb")
public class MultipleMongoProperties {
private MongoProperties primary = new MongoProperties();
private MongoProperties secondary = new MongoProperties();
//getters and setters
}
MultipleMongoConfig class :
#Configuration
#RequiredArgsConstructor
#EnableConfigurationProperties(MultipleMongoProperties.class)
public class MultipleMongoConfig {
#Autowired
private final MultipleMongoProperties mongoProperties;
public MultipleMongoConfig() {
mongoProperties = null;
}
#Primary
#Bean(name = "primaryMongoTemplate")
public MongoTemplate primaryMongoTemplate() throws Exception {
return new MongoTemplate(primaryFactory(this.mongoProperties.getPrimary()));
}
#Bean(name = "secondaryMongoTemplate")
public MongoTemplate secondaryMongoTemplate() throws Exception {
return new MongoTemplate(secondaryFactory(this.mongoProperties.getSecondary()));
}
#Bean
#Primary
public MongoDbFactory primaryFactory(final MongoProperties mongo) throws Exception {
return new SimpleMongoDbFactory(new MongoClient(mongo.getHost(), mongo.getPort()),
mongo.getDatabase());
}
#Bean
public MongoDbFactory secondaryFactory(final MongoProperties mongo) throws Exception {
return new SimpleMongoDbFactory(new MongoClient(mongo.getHost(), mongo.getPort()),
mongo.getDatabase());
}
}
PrimaryMongoConfig :
#Configuration
#EnableMongoRepositories(basePackages = "io.crm.service.repositories",
mongoTemplateRef = "primaryMongoTemplate")
public class PrimaryMongoConfig{
}
SecondaryMongoConfig :
#Configuration
#EnableMongoRepositories(basePackages = "io.crm.service.repositories.report.repositories",
mongoTemplateRef = "secondaryMongoTemplate")
public class SecondaryMongoConfig {
}
The Repository class :
#RepositoryRestResource(collectionResourceRel = "users",path = "users",excerptProjection = UserProjection.class)
public interface UserRepository extends MongoRepository<User, String> {
}
User model class :
#Id
private String id;
private String email;
private String name;
private String businessName;
private String phone;
private String address;
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private Date createdTime;
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private Date updatedTime;
#Field("bookletSignUps")
#DBRef
private List<BookletSignUp> bookletSignUps;
#Field("eventSignUps")
#DBRef
private List<EventSignUp> eventSignUps;
#Field("infoSignUps")
#DBRef
private List<InfoSignUp> infoSignUps;
#Field("webinarSignUps")
#DBRef
private List<WebinarSignUp> webinarSignUps;
The projection :
#Projection(name = "userExcerpt", types = User.class)
public interface UserProjection {
String getId();
String getName();
String getEmail();
String getBusinessName();
String getPhone();
String getAddress();
Date getCreatedTime();
Date getUpdatedTime();
List<BookletSignUp> getBookletSignUps();
List<EventSignUp> getEventSignUps();
List<InfoSignUp> getInfoSignUps();
List<WebinarSignUp> getWebinarSignUps();
}
But when im trying to do a GET request to the REST endpoint http://localhost:9090/users/ im getting java.lang.IllegalArgumentException: Couldn't find PersistentEntity for type class io.crm.service.models.User! exception here. What could be gone wrong here? Ideas will be very much appreciated. Thanks in advance.

Related

Mongo Template querying the wrong collection

I have a mongodb springboot application that is connected to 2 different databases, that have the same collection names and database names but different uris.
Here is my application.properties
spring.data.mongodb.uri = uri
spring.data.mongodb.secondDB.uri = uri
spring.data.mongodb.database = database_name
spring.data.mongodb.secondDB.database = database_name
My AppConfiguration file
#Configuration
public class MultipleMongoConfig {
#Primary
#Bean(name = "newdb1Properties")
#ConfigurationProperties(prefix = "spring.data.mongodb")
public MongoProperties getNewDb1Props() throws Exception {
return new MongoProperties();
}
#Bean(name = "newdb2Properties")
#ConfigurationProperties(prefix = "spring.data.mongodb.secondDB")
public MongoProperties getNewDb2Props() throws Exception {
return new MongoProperties();
}
#Primary
#Bean(name = "newdb1MongoTemplate")
public MongoTemplate newdb1MongoTemplate() throws Exception {
return new MongoTemplate(newdb1MongoDatabaseFactory(getNewDb1Props()));
}
#Bean(name ="newdb2MongoTemplate")
public MongoTemplate newdb2MongoTemplate() throws Exception {
return new MongoTemplate(newdb2MongoDatabaseFactory(getNewDb2Props()));
}
#Primary
#Bean
public MongoDatabaseFactory newdb1MongoDatabaseFactory(MongoProperties mongo) throws Exception {
return new SimpleMongoClientDatabaseFactory(
mongo.getUri()
);
}
#Bean
public MongoDatabaseFactory newdb2MongoDatabaseFactory(MongoProperties mongo) throws Exception {
return new SimpleMongoClientDatabaseFactory(
mongo.getUri()
);
}
Then I set up config files for each data source
#Configuration
#EnableMongoRepositories(basePackages = {"com.example.app.firstDatabse.Repository"},
mongoTemplateRef = "newdb1MongoTemplate"
)
public class NewDb1Config {
}
and
#Configuration
#EnableMongoRepositories(basePackages = {"com.example.app.secondDatabse.Repository"},
mongoTemplateRef = "newdb2MongoTemplate"
)
public class NewDb1Config {
}
For Model I have the following
#AllArgsConstructor
#NoArgsConstructor
#ToSting
#Document(collection = "coll")
public class FirstModel{
#Id
public String id;
#Field("f_name")
public String firstName;
#Field("l_name")
public String lastName;
#Field("age")
public int age;
#Field("gender")
public String gender;
}
and my second Model is the same
#AllArgsConstructor
#NoArgsConstructor
#ToSting
#Document(collection = "coll")
public class SecondModel{
#Id
public String id;
#Field("f_name")
public String firstName;
#Field("l_name")
public String lastName;
#Field("age")
public int age;
#Field("gender")
public String gender;
}
My controller
#ResController
#RequestMapping("/controller")
public class Controller{
#Autowired
private FirstDataabseRepository repo;
#Autowired
private SecondDataabseRepository repo;
#Resource
private MongoTemplate mongoTemplate;
#RequestMapping("/findByName")
public List<SecondModel> findByName(){
Criteria criteria = new Criteria();
criteria = Criteria.where("f_name").is("John");
Query q = new Query(criteria);
List<SecondModel> results = mongoTemplate.find(q,SecondModel.class);
return results;
}
}
So the results show the results of the first collection not the second one. What do I need to do for mongoTemplate to query the second collection not the first one.
Solution
I have to add a qualifier and have a mongoTemplate for each collection
#ResController
#RequestMapping("/controller")
public class Controller{
#Autowired
private FirstDataabseRepository repo;
#Autowired
private SecondDataabseRepository repo;
#Resource
#Qualifier(value="newdb1MongoTemplate")
private MongoTemplate mongoTemplate;
#Resource
#Qualifier(value="newdb2MongoTemplate")
private MongoTemplate mTemplate;
#RequestMapping("/findByName")
public List<SecondModel> findByName(){
Criteria criteria = new Criteria();
criteria = Criteria.where("f_name").is("John");
Query q = new Query(criteria);
List<SecondModel> results = mTemplate.find(q,SecondModel.class);
return results;
}
}

Spring: 2 Repositories out of a single Entity

What I need is 2 Repositories created out of a single entity:
interface TopicRepository implements ReactiveCrudRepository<Topic, String>
interface BackupTopicRepository implements ReactiveCrudRepository<Topic, String>
How is that possible? Right now only one is created.
This is how you would do it.
#Configuration
#ConfigurationProperties(prefix = "mongodb.topic")
#EnableMongoRepositories(basePackages = "abc.def.repository.topic", mongoTemplateRef = "topicMongoTemplate")
#Setter
class TopicMongoConfig {
private String host;
private int port;
private String database;
#Primary
#Bean(name = "topicMongoTemplate")
public MongoTemplate topicMongoTemplate() throws Exception {
final Mongo mongoClient = createMongoClient(new ServerAddress(host, port));
return new MongoTemplate(mongoClient, database);
}
private Mongo createMongoClient(ServerAddress serverAddress) {
return new MongoClient(serverAddress);
}
}
Another configuration
#Configuration
#ConfigurationProperties(prefix = "mongodb.backuptopic")
#EnableMongoRepositories(basePackages = "abc.def.repository.backuptopic", mongoTemplateRef = "backupTopicMongoTemplate")
#Setter
class BackupTopicMongoConfig {
private String host;
private int port;
private String database;
#Primary
#Bean(name = "backupTopicMongoTemplate")
public MongoTemplate backupTopicMongoTemplate() throws Exception {
final Mongo mongoClient = createMongoClient(new ServerAddress(host, port));
return new MongoTemplate(mongoClient, database);
}
private Mongo createMongoClient(ServerAddress serverAddress) {
return new MongoClient(serverAddress);
}
}
Your TopicRepository and BackuoTopicRepository should reside in abc.def.repository.topic and abc.def.repository.backuptopic respectively.
And also you need to have these properties defined in your properties or yml file
mongodb:
topic:
host:
database:
port:
backuptopic:
host:
database:
port:
Lastly, disable springboot autoconfiguration for mongo.
#SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})

Not a managed type during app context initialization

I cannot figure out why entity objects cannot be managed by DAO classes.
I have the following PersistenceConfig file:
#Configuration
#EnableTransactionManagement
#PropertySource({"classpath:persistence"})
#EnableJpaRepositories("com.wx.rm")
public class PersistenceConfig {
#Autowired
private Environment env;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(new String[]{"com.wx.rm"});
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource restDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
Properties hibernateProperties() {
return new Properties() {
{
setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
setProperty("hibernate.format_sql", env.getProperty("hibernate.format_sql"));
setProperty("hibernate.globally_quoted_identifiers",
env.getProperty("hibernate.globally_quoted_identifiers"));
}
};
}
}
Interface IFooAdvertDao:
#Repository("fooAdvertDao")
public interface IFooAdvertDao extends GenericDao<FooAdvert, String> {
}
Interface IBarAdvertDao:
#Repository("barAdvertDao")
public interface IBarAdvertDao extends GenericDao<BarAdvert, Integer> {
}
Base entity BaseAdvert class:
#MappedSuperclass
public abstract class BaseAdvert implements Serializable{
private static final long serialVersionUID = 1L;
#Column(name = "link")
private String link;
#Column(name = "rooms")
private BigDecimal rooms;
public BaseAdvert() {
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public BigDecimal getRooms() {
return rooms;
}
public void setRooms(BigDecimal rooms) {
this.rooms = rooms;
}
}
Entity FooAdvert class:
#Entity
#Table(name = "foo_adverts")
#DynamicUpdate
public class FooAdvert extends BaseAdvert implements Serializable {
#Id
private String id;
#Column(name = "type")
private Integer type;
public FooAdvert() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
}
Entity BarAdvert class:
#Entity
#Table(name = "bar_adverts")
#DynamicUpdate
public class BarAdvert extends BaseAdvert implements Serializable {
#Id
private Integer id;
#Column(name = "status")
private Integer status;
public BarAdvert() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
}
That`s my GenericDao class:
#Repository
public interface GenericDao<T extends Serializable, ID extends Serializable> extends JpaRepository<T, ID> {
}
Generic service class:
public interface GenericService <T extends Serializable, ID extends Serializable> {
T findOne(final ID id);
Page<T> findAll(final Pageable pageable);
long count();
}
Generic service implementation class:
#Service
#Transactional
public class GenericServiceImpl <T extends Serializable, ID extends Serializable> implements GenericService<T, ID> {
#Autowired
private GenericDao<T, ID> genericDao;
public GenericServiceImpl() {
}
public GenericServiceImpl(GenericDao<T, ID> genericDao) {
this.genericDao = genericDao;
}
#Override
#Transactional(readOnly = true)
public T findOne(ID id) {
return genericDao.findOne(id);
}
#Override
#Transactional(readOnly = true)
public Page<T> findAll(Pageable pageable) {
return genericDao.findAll(pageable);
}
#Override
#Transactional(readOnly = true)
public long count() {
return genericDao.count();
}
}
FooAdvertService:
#Service
public class FooAdvertService extends GenericServiceImpl<FooAdvert, String> {
#Autowired
private IFooAdvertDao fooAdvertDao;
}
FooAdvertController class:
#RestController
#RequestMapping("/api")
public class FooAdvertController {
#Autowired
private FooAdvertService fooAdvertService;
#GetMapping("count")
public ResponseEntity getAdvertsCount() {
Long advertsCount = fooAdvertService.count();
return new ResponseEntity(advertsCount, HttpStatus.OK);
}
}
Error message when I try to run my app:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'fooAdvertController': Unsatisfied dependency expressed through field 'fooAdvertService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'fooAdvertService': Unsatisfied dependency expressed through field 'genericDao'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fooAdvertDao': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class org.wixanz.rm.ads.domain.FooAdvert
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'fooAdvertService': Unsatisfied dependency expressed through field 'genericDao'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fooAdvertDao': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class org.wixanz.rm.ads.domain.FooAdvert
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fooAdvertDao': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class org.wixanz.rm.ads.domain.FooAdvert
Caused by: java.lang.IllegalArgumentException: Not a managed type: class org.wixanz.rm.ads.domain.FooAdvert
at org.hibernate.jpa.internal.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:210) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
try to autowire the IFooAdvertDao by name
#Service
public class FooAdvertService extends GenericServiceImpl<FooAdvert, String>
{
#Autowired
#Qualifier("fooAdvertDao")
private IFooAdvertDao fooAdvertDao;
}

Bad Request : org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Failed to bind request element

First Entity:
#Entity
#Table(name = "PIL_P_DOMAINE")
public class PIL_P_DOMAINE {
#NotBlank
#Column(nullable = false, unique = true, name = "DOMAINE_ID")
private String DOMAINE_ID;
#NotBlank
#Column(nullable = false, name = "DOMAINE_DS")
private String DOMAINE_DS;
public PIL_P_DOMAINE() {
}
}
Second Entity:
#Entity
public class PIL_P_DOMAINE_TABLE {
#NotBlank
#JoinColumn(nullable = false, name = "DOMAINE_ID")
#ManyToOne
private PIL_P_DOMAINE DOMAINE_ID;
#NotBlank
#Column(nullable = false, name = "DATABASE_NM")
private String DATABASE_NM;
#NotBlank
#Column(nullable = false, name = "TABLE_NM")
private String TABLE_NM;
#Column(name = "APPLCTN_COLNM_NM")
private String APPLCTN_COLNM_NM;
#Column(name = "CRITERE_FILTRE_NM")
private String CRITERE_FILTRE_NM;
public PIL_P_DOMAINE_TABLE() {
}
}
Converter:
#Component("domaineToDomTabConverter")
public class DomaineToDomTabConverter implements Converter<Object, PIL_P_DOMAINE> {
static final Logger logger = LoggerFactory.getLogger(DomaineToDomTabConverter.class);
#Autowired
#Qualifier("pIL_P_DOMAINE_SERVICE")
IService<PIL_P_DOMAINE> domService;
/**
*
*
* #see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
public PIL_P_DOMAINE convert(Object element) {
Integer id = Integer.parseInt((String) element);
PIL_P_DOMAINE dom = domService.findById(id);
logger.info("Domaine : {}", dom);
return dom;
}
}
AppConfig:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.fussa.fyby")
public class AppConfig extends WebMvcConfigurerAdapter {
#Autowired
DomaineToDomTabConverter domaineToDomTabConverter;
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(domaineToDomTabConverter);
}
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
#Override
public void configurePathMatch(PathMatchConfigurer matcher) {
matcher.setUseRegisteredSuffixPatternMatch(true);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
when i try to persist an PIL_P_DOMAINE object whitout adding
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(domaineToDomTabConverter);
}
to my AppConfig class , to object is persisted (y).
The issue i have is when i want to persist an PIL_P_DOMAINE_TABLE object which contain an object PIL_P_DOMAINE, i added DomaineToDomTabConverter to convert to string i will get in form to the object so i added the converter in my AppCongig class,with those modifications i cant persist an PIL_P_DOMAINE object, i got this error:
WARN :
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
- Failed to bind request element: org.springframework.beans.TypeMismatchException: Failed to convert
value of type [com.fussa.fyby.model.PIL_P_DOMAINE] to required type
[com.fussa.fyby.model.PIL_P_DOMAINE]; nested exception is
org.springframework. core.convert.ConversionFailedException: Failed to
convert from type [com.fussa.fyby.model.PIL_P_DOMAINE] to type
[#javax.validation.Valid #org.springframework.web.bi
nd.annotation.ModelAttribute com.fussa.fyby.model.PIL_P_DOMAINE] for
value 'com.fussa.fyby.model.PIL_P_DOMAINE#716898c0'; nested exception
is java.lang.ClassCastExce ption: com.fussa.fyby.model.PIL_P_DOMAINE
cannot be cast to java.lang.String
How can i call the converter only if i want to persist my second entity and not the first ?
Thanks for any advices..
This issue was fixed by Parameterizing the type i'm converting from to String instead of Object
#Component("domaineToDomTabConverter")
public class DomaineToDomTabConverter implements Converter<String, PIL_P_DOMAINE> {
public PIL_P_DOMAINE convert(Stringelement) {
//
}
}

Spring MongoRepository is Null

I have the following code which attempts to save a POJO object (Actor) into MongoDB using Spring Mongo Repository, but the repository object is always Null. I have followed multiple examples but mainly this one
The POJO class:
#Document(collection = "actors")
public class Actor
{
#Id
private String id;
...
//constructor
//setters & getters
}
The repository:
public interface ActorRepository extends MongoRepository<Actor, String>
{
public Actor findByFNameAndLName(String fName, String lName);
public Actor findByFName (String fName);
public Actor findByLName(String lName);
}
The service that uses the repository:
#Service
public class ActorService
{
#Autowired
private ActorRepository actorRepository;
public Actor insert(Actor a)
{
a.setId(null);
return actorRepository.save(a);
}
}
And I access the service from a REST controller class:
#RestController
public class Controllers
{
private static final Logger logger = Logger.getLogger(Controllers.class);
private static final ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringMongoConfig.class);
private ActorService actorService = new ActorService();
#RequestMapping(value="/createActor", method=RequestMethod.POST)
public #ResponseBody String createActor(#RequestParam(value = "fName") String fName,
#RequestParam(value = "lName") String lName,
#RequestParam(value = "role") String role)
{
return actorService.insert(new Actor(null,fName,lName,role)).toString();
}
...
}
The error that I get is NullPointerException from this line: return actorRepository.save(a); in the ActorService.insert() method.
Any Idea why is this happening?
EDIT: Here is the Spring Configurations
#Configuration
public class SpringMongoConfig extends AbstractMongoConfiguration
{
#Bean
public GridFsTemplate gridFsTemplate() throws Exception
{
return new GridFsTemplate(mongoDbFactory(), mappingMongoConverter());
}
#Override
protected String getDatabaseName()
{
return "SEaaS";
}
#Override
#Bean
public Mongo mongo() throws Exception
{
return new MongoClient("localhost" , 27017 );
}
public #Bean MongoTemplate mongoTemplate() throws Exception
{
return new MongoTemplate(mongo(), getDatabaseName());
}
}
The problem is that you are not using Spring to get the ActorService dependency -instead you have manually instantiated the dependency using
private ActorService actorService = new ActorService();.
The following code is the easiest fix in order to inject the ActorService dependency into the controller.
#RestController
public class Controllers
{
private static final Logger logger = Logger.getLogger(Controllers.class);
private static final ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringMongoConfig.class);
#Autowired
private ActorService actorService;
#RequestMapping(value="/createActor", method=RequestMethod.POST)
public #ResponseBody String createActor(#RequestParam(value = "fName") String fName,
#RequestParam(value = "lName") String lName,
#RequestParam(value = "role") String role)
{
return actorService.insert(new Actor(null,fName,lName,role)).toString();
}
...
}

Resources