Ma Kro
Ma Kro

Reputation: 1242

Autowire MongoRepository in Spring MVC

I want to Autowire MongoRepository into my service class, and I'm not able to do this. I'm using java config. This is my repository class:

@Repository
public interface UserRepository extends MongoRepository<User, String> {

    public User findByFirstName(String firstName);
    public List<User> findByLastName(String lastName);

}

This is the Service which uses UserRepository:

@Service
public class TestService {

    @Autowired
    private UserRepository repository;

    public void save(User user) {
        repository.save(user);
    }
}

This is part of my Controller which uses service:

@Controller
public class TestController {

    @Autowired
    private TestService service;

My main java config class looks like this:

@Configuration
@EnableWebMvc
@EnableMongoRepositories
@Import({MjurAppConfig.class, MongoConfiguration.class})
@ComponentScan({"prv.makro.mjur.controller"})
public class MjurWebAppConfig extends WebMvcConfigurerAdapter {

MjurAppConfig:

@Configuration
@ComponentScan({"prv.makro.mjur.dao", "prv.makro.mjur.repository"})
public class MjurAppConfig {

    @Bean
    public User getUser() {
        return new User();
    }

    @Bean
    public TestService getTestService() {
        return new TestService();
    }
}

And mongo config:

@Configuration
public class MongoConfiguration {

    @Bean
    public MongoFactoryBean mongo() {
        MongoFactoryBean mongo = new MongoFactoryBean();
        mongo.setHost("localhost");
        mongo.setPort(27017);
        return mongo;
    }

    @Bean
    public MongoTemplate mongoTemplate() throws Exception{
        return new MongoTemplate(mongo().getObject(),"mjur");
    }
}

Exception:

    Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private prv.makro.mjur.repository.UserRepository 
prv.makro.mjur.service.impl.FirstService.repository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type [prv.makro.mjur.repository.UserRepository] 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)}

I was searching for resolution for this problem but I couldn't find anything. IMO Component scan should find the repository and it should bind it to spring context. Sadly it's not working like that.

Upvotes: 8

Views: 13535

Answers (3)

Ma Kro
Ma Kro

Reputation: 1242

Ok, the problem was with @EnableMongoRepositories annotation.

When I have added package name to it's body (so it looked like:

@EnableMongoRepositories({"prv.makro.mjur.repository"}) )

I was able to autowire my UserRepository

Upvotes: 17

  1. Create your repository interface with @NoRepositoryBean annotation.
@NoRepositoryBean
public interface MyRepository<T, ID extends Serializable> extends MongoRepository<T, ID> {

}
  1. Create your Repository implementation
public class MyRepositoryImpl<T, ID extends Serializable>
    extends SimpleMongoRepository<T, ID> {

    public PermissableRepositoryImpl(
        final MongoEntityInformation<T, ID> metadata,
        final MongoOperations mongoOperations
    ) {

        super(metadata, mongoOperations);
    }
}
  1. Add @EnableMongoRepository annotation to your appropriate Configuration or Application class.
@ComponentScan(basePackages = {"com.company"})
@EnableMongoRepositories(repositoryBaseClass = MyRepositoryImpl.class)
@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    public static void main(final String[] args) {

        SpringApplication.run(Application.class, args);
    }

    @Override
    protected final SpringApplicationBuilder configure(final SpringApplicationBuilder applicationBuilder) {

        return applicationBuilder.sources(Application.class);
    }
}

Upvotes: 1

dimitrisli
dimitrisli

Reputation: 21381

EDIT (after comments and alter of the posted code)

This is happening because the Spring Web application has 2 contexts: 1 is the root context and another one is the Web context (the one you register by the @EnableWebMvc annotation).

Please do the following:

1) Remove the @Import annotation from your MjurWebAppConfig - remember this is your web context. 2) Add the @Import in the MjurAppConfig config essentially looking like:

@Configuration
@Import({MongoConfiguration.class})
@ComponentScan({"prv.makro.mjur.dao", "prv.makro.mjur.repository"})
public class MjurAppConfig {
//..

These steps should make visible your autowired DAO bean inside your Service bean.


Before EDIT:

I bet your TestService bean is under package prv.makro.mjur.service judging by the component scan annotation:

@ComponentScan({"prv.makro.mjur.controller"})

In other words @ComponentScan cannot see your TestService to register the @Autowired dependency.

Make sure TestService is visible by your component scan and under the above assumption if you do:

@ComponentScan({"prv.makro.mjur"})

it should work.

Upvotes: 0

Related Questions