0

I am trying to add custom behavior to all repositories in my spring boot application only with annotations. Official documentation deals with JPA and not for MongoDB.

I have not created any custom methods yet as I want to check whether the default is working fine.

My code is as follows:



    src/main/java/com/test/shipper/database:
    MongoConfig.java

    src/main/java/com/test/shipper/modal:
    Shipper.java

    src/main/java/com/test/shipper/repository:
    BaseRepositoryFactoryBean.java
    BaseRepositoryImpl.java
    BaseRepository.java
    ShipperRepository.java

    src/main/java/com/test/shipper/service:
    ShipperService.java

ShipperService.java



    public class ShipperService {
        @Autowired
        private ShipperRepository repository;

        public Shipper createShipper(Shipper shipper){

            repository.deleteAll();

            Shipper shipper1 = new Shipper("123","shipper123");
            repository.insert(shipper1);

            Shipper shipper2 = new Shipper("234","shipper234");
            repository.insert(shipper2);
            System.out.println("Find All!!");
            List  shippers = repository.findAll();
            for (Shipper car: shippers) {System.out.println(car);}
            repository.delete(shipper2.getShipperId());
            shippers = repository.findAll();
            for (Shipper car: shippers) {
                System.out.println(car);
            }
            return null;
        }
    }

MongoConfig.java



    @Configuration
    @EnableMongoRepositories(basePackages = "com.test.shipper",
            repositoryFactoryBeanClass = com.test.shipper.repository.BaseRepositoryFactoryBean.class)
    public class MongoConfig extends AbstractMongoConfiguration {

        @Value("test")
        private String dbName;

        @Value("127.0.0.1")
        private String host;

        @Value("27017")
        private int port;

        @Override
        protected String getDatabaseName() {
            return dbName;
        }
        @Bean
        @Override
        public Mongo mongo() throws Exception {
            return new MongoClient(host, port);
        }
        @Bean
        public MongoTemplate mongoTemplate() throws Exception {
            return new MongoTemplate(mongo(), dbName);
        }
    }

BaseRepository.java



@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable>
        extends MongoRepository<T, ID>
{

}

BaseRepositoryImpl.java



    @NoRepositoryBean
    public class BaseRepositoryImpl
            extends SimpleMongoRepository implements BaseRepository
    {
        private MongoOperations mongoOperations;

        public BaseRepositoryImpl(MongoEntityInformation metadata,
                                  MongoOperations mongoOperations) {
            super(metadata, mongoOperations);
            this.mongoOperations = mongoOperations;
        }

    }

BaseRepositoryFactoryBean.java



    public class BaseRepositoryFactoryBean, T, I extends Serializable>
            extends MongoRepositoryFactoryBean {

        public BaseRepositoryFactoryBean(Class repositoryInterface) {

            super(repositoryInterface);
        }

        @Override
        protected RepositoryFactorySupport getFactoryInstance(
                MongoOperations operations) {
            return new BaseMongoRepositoryFactory( operations );
        }

        private static class BaseMongoRepositoryFactory
                extends MongoRepositoryFactory {

            private MongoOperations mongo;
            public BaseMongoRepositoryFactory(MongoOperations mongoOperations) {
                super(mongoOperations);
                this.mongo = mongoOperations;
            }

            @SuppressWarnings("unchecked")
            protected Object getTargetRepository(RepositoryMetadata metadata) {

                TypeInformation information =  ClassTypeInformation.from((Class)metadata.getDomainType());
                MongoPersistentEntity pe = new BasicMongoPersistentEntity(information);
                MongoEntityInformation mongometa =
                        new MappingMongoEntityInformation(pe);

                return new BaseRepositoryImpl( mongometa,  mongo);
            }

            protected Class getRepositoryBaseClass(RepositoryMetadata metadata) {

                return BaseRepository.class;
            }
        }
    }

ShipperRepository.java



    @Repository
    public interface ShipperRepository
            extends BaseRepository{
    }

Shipper.java




     @Document(collection = "shipper")
        public class Shipper{

            @Id
            private String shipperId;
            private String shipperName;
            public Shipper() {
            }
            public Shipper(String shipperId, String shipperName) {
                this.shipperId = shipperId;
                this.shipperName = shipperName;
            }

            public String getShipperId() {
                return shipperId;
            }

            public void setShipperId(String shipperId) {
                this.shipperId = shipperId;
            }

            public String getShipperName() {
                return shipperName;
            }

            public void setShipperName(String shipperName) {
                this.shipperName = shipperName;
            }
        }

When the application starts I am getting the following exception.


    Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
    2017-08-06 23:08:26.849 ERROR 12828 --- [           main] o.s.boot.SpringApplication               : Application startup failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'shipperService': Unsatisfied dependency expressed through field 'repository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shipperRepository': Invocation of init method failed; nested exception is java.lang.IllegalStateException: No suitable constructor found on interface com.test.shipper.repository.BaseRepository to match the given arguments: [class org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation, class org.springframework.data.mongodb.core.MongoTemplate]. Make sure you implement a constructor taking these
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.6.RELEASE.jar!/:1.5.6.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.6.RELEASE.jar!/:1.5.6.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.6.RELEASE.jar!/:1.5.6.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.6.RELEASE.jar!/:1.5.6.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.6.RELEASE.jar!/:1.5.6.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.6.RELEASE.jar!/:1.5.6.RELEASE]
    at com.test.shipper.ShipperApplication.main(ShipperApplication.java:12) [classes!/:0.0.1-SNAPSHOT]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_131]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_131]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_131]
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) [shipper_microservice-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) [shipper_microservice-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) [shipper_microservice-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51) [shipper_microservice-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shipperRepository': Invocation of init method failed; nested exception is java.lang.IllegalStateException: No suitable constructor found on interface com.test.shipper.repository.BaseRepository to match the given arguments: [class org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation, class org.springframework.data.mongodb.core.MongoTemplate]. Make sure you implement a constructor taking these
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    ... 27 common frames omitted
Caused by: java.lang.IllegalStateException: No suitable constructor found on interface com.test.shipper.repository.BaseRepository to match the given arguments: [class org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation, class org.springframework.data.mongodb.core.MongoTemplate]. Make sure you implement a constructor taking these
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getTargetRepositoryViaReflection(RepositoryFactorySupport.java:360) ~[spring-data-commons-1.13.6.RELEASE.jar!/:na]
    at org.springframework.data.mongodb.repository.support.MongoRepositoryFactory.getTargetRepository(MongoRepositoryFactory.java:98) ~[spring-data-mongodb-1.10.6.RELEASE.jar!/:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:199) ~[spring-data-commons-1.13.6.RELEASE.jar!/:na]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:277) ~[spring-data-commons-1.13.6.RELEASE.jar!/:na]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:263) ~[spring-data-commons-1.13.6.RELEASE.jar!/:na]
    at org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean.afterPropertiesSet(MongoRepositoryFactoryBean.java:117) ~[spring-data-mongodb-1.10.6.RELEASE.jar!/:na]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.10.RELEASE.jar!/:4.3.10.RELEASE]
    ... 37 common frames omitted

</code></pre>

What could be the issue?

John
  • 101
  • 1
  • 3
  • It would be sufficient to declare `@EnableMongoRepositories(repositoryBaseClass = BaseRepositoryImpl.class)` instead of creating an own repository factory to enhance all repositories. Provide generic type arguments to `ShipperRepository ` otherwise the repository infrastructure is not able to determine the id/domain type. Your configuration from the config class isn't applied but rather Spring Boot's auto-config kicks in. Remove your `MongoConfig` class and place `@EnableMongoRepositories` on your Spring Boot application class. – mp911de Aug 07 '17 at 07:50
  • I changed the application as mentioned above and the interface definition of ShipperRepository as "public interface ShipperRepository extends BaseRepository" but I am getting the error when the application starts,o.s.boot.SpringApplication : Application startup failed – John Aug 07 '17 at 14:54
  • org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'shipperService': Unsatisfied dependency expressed through field 'repository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shipperRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.model.MappingException: Could not lookup mapping metadata for domain class java.lang.Object! – John Aug 07 '17 at 14:56
  • ShipperRepository ought to be declared as `ShipperRepository extends BaseRepository` – mp911de Aug 07 '17 at 17:38
  • Hi I answered [in my post](https://stackoverflow.com/a/62475750/4020329) I hope you find it useful – Ali Yeganeh Jun 19 '20 at 17:44

0 Answers0