Not an managed type for Spring Data Mongodb - spring

I have the following mongo configuration:
<context:component-scan base-package="com.example" />
<mongo:repositories base-package="com.example.repositories.mongodb" />
I have the repository as follows:
package com.example.repositories.mongodb;
public interface ReviewRepository extends CrudRepository<Review, String> {...}
and the bean:
package com.example.domain;
#Document(collection="Review")
public class Review implements Serializable { ... }
Unfortunately, when I start the app, I get the following exception:
Caused by: org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private
com.example.repositories.mongodb.ReviewRepository
com.example.Controller.reviewRepository; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'reviewRepository': FactoryBean threw
exception on object creation; nested exception is
java.lang.IllegalArgumentException: Not an managed type: class
com.example.domain.Review
....
Caused by: java.lang.IllegalArgumentException: Not an managed type:
class com.example.domain.Review
I think that this might be caused by the repository and the bean it manages not being in the same package. But I get the same issue also when I do place them in the same package. Any ideas?

In the same project we were also using mysql and it was scanning the package: com.example.repositories. This caused the issue and once we changed it to com.example.repositories.mysql it was solved.

Related

Spring Data: Mongo Repository can not be initialized

I'm getting this strange error message when I start my spring boot service:
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property storeMpi found for type Patient!
Service can't be started since this exception is raised.
My code is very straight:
public interface PatientRepository
extends MongoRepository<Patient, String>,
QuerydslPredicateExecutor<Patient>,
MPIPatientRepository
{
}
public interface MPIPatientRepository {
Patient storeMpi(Patient patient);
}
You can see, that storeMpi is a method, not an expected field of my Patient entity.
Implementation is straight as well:
#Repository
#RequiredArgsConstructor
public class MPIPatientRepository implements cat.gencat.catsalut.hes.mpi.repository.MPIPatientRepository {
private final MongoTemplate mongoTemplate;
/**
* {#inheritDoc}
*/
#Override
public Patient storeMpi(Patient patient) {
return this.mongoTemplate.save(patient);
}
I don't quite figure out what's wrong.
Formatted root CausedBy is:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ca.uhn.fhir.spring.boot.autoconfigure.FhirAutoConfiguration$FhirRestfulServerConfiguration': Bean instantiation via constructor failed;
nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [ca.uhn.fhir.spring.boot.autoconfigure.FhirAutoConfiguration$FhirRestfulServerConfiguration$$EnhancerBySpringCGLIB$$5fe4b535]: Constructor threw exception;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'patientResourceProvider' defined in file [/home/jeusdi/projects/salut/mpi/hes-mpi-fhir-mongodb/target/classes/cat/gencat/catsalut/hes/mpi/providers/PatientResourceProvider.class]: Unsatisfied dependency expressed through constructor parameter 0;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'patientService' defined in file [/home/jeusdi/projects/salut/mpi/hes-mpi-fhir-mongodb/target/classes/cat/gencat/catsalut/hes/mpi/service/PatientService.class]: Unsatisfied dependency expressed through constructor parameter 2;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'patientRepository' defined in cat.gencat.catsalut.hes.mpi.repository.PatientRepository defined in #EnableMongoRepositories declared on MongoRepositoriesRegistrar.EnableMongoRepositoriesConfiguration: Invocation of init method failed;
nested exception is org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract cat.gencat.catsalut.hes.mpi.model.Patient cat.gencat.catsalut.hes.mpi.repository.MPIPatientRepository.storeMpi(cat.gencat.catsalut.hes.mpi.model.Patient)! Reason: No property storeMpi found for type Patient!;
nested exception is org.springframework.data.mapping.PropertyReferenceException: No property storeMpi found for type Patient!
Any ideas?

EnversRevisionRepositoryFactoryBean dosenot create bean for JPARepositories

I am using spring boot, hibernate enverse. I have following dependency in pom.xml
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-envers</artifactId>
</dependency>
following is my envers config.
#Configuration
#EnableJpaRepositories(repositoryFactoryBeanClass =
EnversRevisionRepositoryFactoryBean.class, basePackages = {
"com.example.persistence" })
public class EnversConf
{
}
So package com.example.persistence have PersonDAO and AddressDAO and also Entities.
I have following two DAOs,
interface PersonDAO extends RevisionRepository<PersonEntity, Integer, Integer>, JpaRepository<PersonEntity, Integer>{}
interface AddressDAO extends JpaRepository<AddressEntity, Integer>{}
I have two entities PersonEntity which I want to audit and AddressEntity which I don't want to audit.
Now I have following two services,
class PersonServiceImpl implements PersonService{
#Autowire PersonDAO personDAO;
}
class AddressServiceImpl implements AddressService{
#Autowire AddressDAO addressDAO;
}
When I add #EnableJpaRepositories(...) config it unable to get beans for AddressDAO. I thought EnversRevisionRepositoryFactoryBean works for both RevisionRepository and JpaRepository.
I got following exception stacktrace,
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'addressService': Unsatisfied dependency expressed through field 'addressDAO'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'addressDAO': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property findAll found for type AddressEntity!
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'addressDAO': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property findAll found for type AddressEntity!
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property findAll found for type AdressEntity!
Am I missing any configuration.
Got solution ;)
Need to create two separate configuration classes as we cannot use TWO #EnableJpaRepositories on same configuration class.
So have created following two configuration classes,
#EnableJpaRepositories(basePackages = "com.example.jpa.dao")
class JpaConfig {}
#EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean, basePackages = "com.example.envers.dao")
class EnversConfig {}

Instantiation of bean failed : Specified class is an interface

I am facing an issue while creating a bean for dependency injection. Here is the scenario.
I am dealing with MongoDB repository, I have also created a class which uses it. I am trying to instantiate bean instance of both.
MongoDB reporsitory:
#Repository
public interface ProductGlobalTrendRepository extends MongoRepository<ProductGlobalTrend,String>{
public ProductGlobalTrend findByPid(#Param("pId") String pId);
}
The class which is using it:
#Service
#Scope("singleton")
public class ProductTrendService {
#Autowired
#Qualifier("productGlobalTrendRepo")
ProductGlobalTrendRepository productGlobalTrendRepo;
public ProductTrendService() {
super();
}
public void setProductGlobalTrendRepo(
ProductGlobalTrendRepository productGlobalTrendRepo) {
this.productGlobalTrendRepo = productGlobalTrendRepo;
}
public ProductTrendService(ProductGlobalTrendRepository productGlobalTrendRepo) {
super();
this.productGlobalTrendRepo = productGlobalTrendRepo;
}
}
The spring's bean config xml has these entries:
<bean id="productTrendService" class="com.api.services.ProductTrendService"> </bean>
<bean id="productGlobalTrendRepo" class="com.mongodb.repository.ProductGlobalTrendRepository"> </bean>
Following is the error I am getting:
19428 [localhost-startStop-1] WARN
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
- Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'productTrendService': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: com.mongodb.repository.ProductGlobalTrendRepository
com.api.services.ProductTrendService.productGlobalTrendRepo; nested
exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'productGlobalTrendRepo' defined in
class path resource [com/vstore/conf/spring-security.xml]:
Instantiation of bean failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [com.mongodb.repository.ProductGlobalTrendRepository]:
Specified class is an interface
It complains that repository is a interface class.
Can somebody please suggest a fix/workaround for this bean dependency injection ?
The problem is with the following information in your context file
<bean id="productGlobalTrendRepo"
class="com.mongodb.repository.ProductGlobalTrendRepository">
</bean>
You should create a class com.mongodb.repository.ProductGlobalTrendRepositoryImpl which implements com.mongodb.repository.ProductGlobalTrendRepository and provides implementation of its methods.
then change your bean declaration info as
<bean id="productGlobalTrendRepo"
class="com.mongodb.repository.ProductGlobalTrendRepositoryImpl">
</bean>
Behind the scene the object is created which is not possible with the interface.

MongoDB configuration in Spring Boot and Spring Data REST

I want to use MongoDB for the mongoDB with spring-boot and JPA.. I'm able to do with embedded H2 database. But I'm not sure what's going wrong using mongo-db. While running the application, I'm getting error that datasource is missing.
#EnableAutoConfiguration
#EnableJpaRepositories(basePackages = "com..........repo")
#EnableWebMvc
#Configuration
#ComponentScan
#Import({ SpringMongoConfig.class, RepositoryRestMvcConfiguration.class })
public class Bootstrap extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args);
}
#Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder application) {
return application.sources(Bootstrap.class);
}
}
.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
#Configuration
#EnableMongoRepositories(basePackages = "com.............repo")
#PropertySource(value = "classpath:mongo-config.properties")
public class SpringMongoConfig extends AbstractMongoConfiguration {
#Value("${MONGO_DB_HOST}")
private String MONGO_DB_HOST;
#Value("${MONGO_DB_PORT}")
private int MONGO_DB_PORT;
#Value("${DB}")
private String DB;
#Override
protected String getDatabaseName() {
return DB;
}
#Bean
#Override
public Mongo mongo() throws Exception {
return new MongoClient(MONGO_DB_HOST, MONGO_DB_PORT);
}
}
.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.dataSource; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$NonEmbeddedConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public javax.sql.DataSource org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$NonEmbeddedConfiguration.dataSource()] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath.
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:293)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1186)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
..........................
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.dataSource; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$NonEmbeddedConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public javax.sql.DataSource org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$NonEmbeddedConfiguration.dataSource()] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath.
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:509)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:290)
... 25 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$NonEmbeddedConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public javax.sql.DataSource org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$NonEmbeddedConfiguration.dataSource()] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath.
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:597)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1095)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:990)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
....................................
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public javax.sql.DataSource org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$NonEmbeddedConfiguration.dataSource()] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath.
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:188)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:586)
... 39 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath.
at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.getDriverClassName(DataSourceProperties.java:93)
at org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$NonEmbeddedConfiguration.dataSource(DataSourceAutoConfiguration.java:105)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
For starters use the framework Spring Boot will do autoconfiguration for the frameworks it detects. This includes Spring Data JPA and Spring Data Mongo. So you can remove the #Enable annotation for it.
The same for Spring MVC and Spring Data Rest.
To allow Spring Boot to configure Spring Mongo add the following properties to your application.properties
spring.data.mongodb.host= # the db host
spring.data.mongodb.port=27017 # the connection port (defaults to 27107)
or the
spring.data.mongodb.uri=mongodb://localhost/test # connection URL
More on the Spring Boot Mongo support can be found in this section of the Spring Boot Reference Guide.
When not using an embedded datasource you have to specify which driver to use for this add the following property to your application.properties. This is also documented in this section of the Spring Boot Reference Guide.
spring.datasource.driverClassName=your.driver.class
I suggest moving your Bootstrap class to a top level package and remove all not needed annotations and configuration files
#EnableAutoConfiguration
#Configuration
#ComponentScan
public class Bootstrap extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Bootstrap.class);
}
}
Should be enough to bootstrap your whole application including jpa, mongo and web support.
For a quite complete list I suggest Appendix A of the Spring Boot Reference Guide.

Failed to load ApplicationContext in JUnit with JNDI datasource

I have some troubles testing my application, whereas it works well in normal execution.
I think it comes from JNDI resources which are not found, but I don't understand why and how to fix it.
When I start my Junit test, I got this error:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
at ...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DAOImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource com.sample.DAOImpl.myDatasource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=myDatasource)}
Related cause: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myDatasource' defined in URL [file:src/test/resources/spring/test-dao-config.xml]: Invocation of init method failed; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
at ...
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource com.sample.DAOImpl.myDatasource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=myDatasource)}
at ...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=myDatasource)}
at ..
Here is my configuration:
Context.xml
<Resource name="jdbc/myDatasource" auth="Container" type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#database:99999:instance"
username="user"
password="password"
validationQuery="select 1 from dual"
testOnBorrow ="true"
maxActive="5"
maxIdle="1"
maxWait="-1" />
test-dao-config.xml
<bean id="myDatasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/myDatasource" />
</bean>
DaoImpl
#Repository
public class DacsDAOImpl implements DacsDAO
{
private final static Logger LOGGER = LoggerFactory.getLogger(DAOImpl.class);
#Autowired
#Qualifier("myDatasource")
private DataSource myDatasource;
....
}
And my tests
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "file:src/test/resources/spring/test-dao-config.xml" })
public class MyDAOImplTest
{
private MyDAO dao;
#BeforeClass
public static void initJndi() throws IllegalStateException, NamingException
{
//some test, but doesn't work
// SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
// builder.bind("java:comp/env/jdbc/myDatasource", "myDatasource");
// builder.activate();
}
#Before
public void setUp() throws IllegalStateException, NamingException
{
dao = new MyDAOImpl();
}
#Test
public void testTotalUser()
{
int result = dao.getTotalUser();
Assert.assertEquals(0, result);
}
}
Thanks
You are running in a test case so everything in your Context.xml isn't available as that is only available on tomcat. Why do you need a jndi lookup in your test case anyway? If you want to test your dao use an in-memory database like hsql, h2 or derby and use that instead. Spring has some nice tags to make it easy for you.
<jdbc:embedded-database id="myDataSource" type="H2">
// Add some init scripts here.
</jdbc:embedded-database>
If you really need to do a JNDI lookup you are almost there in your test case. However you have to register a DataSource not a String. So you still will need to construct some (in-memory) datasource and bind that to the mock jndi location
#BeforeClass
public static void initJndi() throws IllegalStateException, NamingException
{
//some test, but doesn't work
// Construct in-memory database
SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
builder.bind("java:comp/env/jdbc/myDatasource", myDatasource); //Actual datasource not a String!
builder.activate();
}
And finally your test is also flawed, you are loading your context but aren't doing anything with it. You are constructing a MyDAOImpl in your #Before method. Why even bother loading the context as you are doing nothing with.

Resources