MongoDB and Spring JPA integration is throwing error - spring

I am trying to integrate Spring JPA with MongoDB. My intention is to just retrieve data from mongo DB. I am getting the below error while injecting my repository.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.org.coop.society.data.mongo.repositories.MaterialMasterRepository com.org.coop.security.service.MongoService.materialMasterRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'materialMasterRepository': Invocation of init method failed; nested exception is java.lang.AbstractMethodError
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
My configuration snippet is given below.
TestMongoDBConfig.java
#Configuration
#EnableMongoRepositories(basePackages = {"com.abc.data.mongo.repositories"})
#ComponentScan(basePackages = "com.abc")
#PropertySource("classpath:applicationTest.properties")
public class TestMongoDBConfig extends AbstractMongoConfiguration {
#Autowired
private Environment env;
#Override
protected String getDatabaseName() {
return "retail";
}
#Override
#Bean
public MongoClient mongo() throws Exception {
MongoClient client = new MongoClient("localhost", 27017);
return client;
}
#Override
protected String getMappingBasePackage() {
return "com.abc.data.mongo.entities";
}
#Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), getDatabaseName());
}
}
MaterialMaster.java in com.abc.data.mongo.entities package
#Document(collection = "materialMaster")
public class MaterialMaster {
#Id
private Long materialId;
#Field
private String name;
MaterialMasterRepository.java in com.abc.data.mongo.repositories package
public interface MaterialMasterRepository extends MongoRepository<MaterialMaster, Long> {
}
MongoService.java in com.abc.service package
#Service
public class MongoService {
#Autowired
private MaterialMasterRepository materialMasterRepository;
public void getMaterials() {
List<MaterialMaster> materials = materialMasterRepository.findAll();
System.out.println(materials);
}
}
Junit class looks like below
#RunWith(SpringJUnit4ClassRunner.class)
#ComponentScan(basePackages = "com.abc")
#ContextHierarchy({
#ContextConfiguration(classes={TestMongoDBConfig.class})
})
public class ModuleWSTest {
#Autowired
private MongoService mongoService;
#Test
public void testModule() {
mongoService.getMaterials();
}
}
I have tried all possible changes (as per my knowledge) but no luck. Any help is really appreciated.

The error message is little confusing. I was using latest spring-data-mongodb (1.8.4.RELEASE). Once I downgraded the dependency to 1.6.0.RELEASE then the above configuration started working.

Related

How to do integration testing for custom mongo repository?

These are the following configuration that I have done in my project.
#Configuration
public class AppMongoConfig {
#Autowired private MongoDbFactory mongoDbFactory;
#Autowired private MongoMappingContext mongoMappingContext;
#Bean
public MappingMongoConverter mappingMongoConverter() {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory);
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext);
converter.setTypeMapper(new DefaultMongoTypeMapper(null));
return converter;
}
}
#Configuration
#RequiredArgsConstructor
#EnableConfigurationProperties(MultipleMongoProperties.class)
public class MultipleMongoConfig {
private final MultipleMongoProperties mongoProperties;
#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 MongoClientURI(mongo.getUri()));
}
#Bean
public MongoDbFactory secondaryFactory(final MongoProperties mongo) throws Exception {
return new SimpleMongoDbFactory(new MongoClientURI(mongo.getUri()));
}
}
#Data
#ConfigurationProperties(prefix = "mongodb")
public class MultipleMongoProperties {
private MongoProperties primary = new MongoProperties();
private MongoProperties secondary = new MongoProperties();
}
#Configuration
#EnableMongoRepositories(
basePackages = {"com.student.repository.primary"},
mongoTemplateRef = "primaryMongoTemplate")
public class PrimaryMongoConfig {}
#Configuration
#EnableMongoRepositories(
basePackages = {"com.student.repository.secondary"},
mongoTemplateRef = "secondaryMongoTemplate")
public class SecondaryMongoConfig {}
Repository code:
public interface StudentDAO {
Student save(StudentInfo studentInfo);
}
#Repository
public class StudentDAOImpl implements StudentDAO {
#Autowired #Qualifier("primaryMongoTemplate")
private MongoTemplate mongoTemplate;
#Override public StudentInfo save(StudentInfo userWatchlist) {
return mongoTemplate.save(userWatchlist);
}
}
Integration Testing code:
#RunWith(SpringRunner.class)
#DataMongoTest(includeFilters = #Filter(Repository.class))
public class WatchListDAOImplIT {
#Autowired private StudentDAO studentDAO;
#Test
public void save() {
StudentInfo studentInfo = getStudentInfo();
StudentInfo dbUserWatchlist = watchListDAO.save(studentInfo);
Assert.assertEquals(studentInfo.getId(), dbUserWatchlist.getId());
}
private StudentInfo getStudentInfo() {
StudentInfo studentInfo = new StudentInfo();
studentInfo.setId(9999999l);
return studentInfo;
}
}
Which is giving me following error:-
java.lang.IllegalStateException: Failed to load ApplicationContext
at
org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125)
at
org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108)
at
org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:
: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'appMongoConfig': Unsatisfied dependency
expressed through field 'mongoDbFactory'; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'primaryFactory' defined in class path
resource [.../config/mongo/MultipleMongoConfig.class]: Unsatisfied
dependency expressed through method 'primaryFactory' parameter 0;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'org.springframework.boot.autoconfigure.mongo.MongoProperties'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations: {}
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'org.springframework.boot.autoconfigure.mongo.MongoProperties'
available: expected at least 1 bean which

Spring: Register a component within a test class

I am registering an ErrorHandler for my Spring Scheduler and would like to test that is is correctly registered in a SpringTest
So far I have tried:
Handler
#Component
public class ScheduledErrorHandler implements ErrorHandler {
#Autowired
private ErrorService errorService;
#Override
public void handleError(final Throwable t) {
errorService.handle(t);
}
}
Registering the Handler
#EnableScheduling
#Configuration
public class SchedulingConfiguration implements SchedulingConfigurer {
#Autowired
private ScheduledErrorHandler handler;
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(1);
scheduler.setErrorHandler(handler);
scheduler.initialize();
taskRegistrar.setScheduler(scheduler);
}
//...
}
Testing it's registered
#ContextConfiguration(classes = {
SchedulerConfiguration.class,
SchedulerErrorHandler.class
})
#RunWith(SpringRunner.class)
public class SchedulerErrorHandlerTest {
#MockBean
private ErrorService service;
#Autowired
private ExampleScheduledJob job;
#Test
public void verifyHandlerGetsCalled() {
// Wait until the job runs
if(!job.latch.await(5, SECONDS)) {
fail("Job never ran");
}
verify(service).handle(any(RuntimeException.class));
}
#Component
public static class ExampleScheduledJob {
private final CountDownLatch latch = new CountDownLatch(1);
#Scheduled(fixedRate=1000)
public void run() {
latch.countDown();
throw new RuntimeException("error");
}
}
}
However when I do this I get a DependencyNotFound error saying Spring cannot create my test class as no Bean named ExampleScheduledJob can be found. How can I register it only for the sake of this test?
Error creating bean with name
'com.example.demo.SchedulerErrorHandlerTest': Unsatisfied dependency
expressed through field 'job'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'com.example.demo.SchedulerErrorHandlerTest$ExampleScheduledJob'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
This should work
#ContextConfiguration(classes = {
SchedulingConfiguration.class,
SchedulerErrorHandlerTest.ExampleScheduledJob.class,
ScheduledErrorHandler.class
})
#RunWith(SpringRunner.class)
You can register your test configuration class (ExampleScheduledJob) as indicated above. Since it is a static inner class, you need to use it like SchedulerErrorHandlerTest.ExampleScheduledJob

Spring Boot - Spring Data giving Error creating bean with name 'dataSourceInitializerPostProcessor' error

I have a spring boot spring data application. This was working fine when my repository extended CrudRepository. To get dynamic querying, I extended QueryByExampleExecutor. After extending QueryByExampleExecutor, and run the mvn spring-boot:run, I am getting the below error:
***An exception occured while running. null: InvocationTargetException: Error creating bean with name 'dataSourceInitializerPostProcessor': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.beans.factory.BeanFactory org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerPostProcessor.beanFactory; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employeeProfileRepository': Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)***
Repository Class:
#Transactional
#Repository
public interface EmployeeProfileRepository extends CrudRepository<EmployeeProfile, Long>, QueryByExampleExecutor<EmployeeProfile> {
}
Service Class:
#Service
public class EmployeeProfileService {
#Autowired
private EmployeeProfileRepository empProfileRepository;
public List<EmployeeProfile> searchEmployees(Long id, String firstName, String lastName) {
List<EmployeeProfile> employees = new ArrayList<>();
EmployeeProfile emp = new EmployeeProfile();
emp.setId(id);
emp.setFirstName(firstName);
emp.setLastName(lastName);
Example<EmployeeProfile> example = Example.of(emp);
Iterable<EmployeeProfile> iterable = empProfileRepository.findAll(example);
iterable.forEach(employees::add);
return employees;
}
}
Application class:
#Configuration
#EnableAutoConfiguration
#EnableJpaRepositories("com.employee.dao")
#ComponentScan("com.employee")
#EntityScan("com.employee.dto")
public class Application extends SpringBootServletInitializer {
public static void main(final String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
protected final SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}

Unable to autowire dozer Mapper in component class in spring boot

I am new to Spring Boot. I was trying to develop small application in spring boot mvc with neo4j database. Following is my Server
#Configuration
#ComponentScan({ "myproject" })
#EnableAutoConfiguration
#EnableNeo4jRepositories(basePackages = "myproject")
public class Server extends Neo4jConfiguration implements CommandLineRunner
{
public Server()
{
setBasePackage("myproject");
}
#Bean
SpringRestGraphDatabase graphDatabaseService()
{
return new SpringRestGraphDatabase("http://localhost:7474/db/data");
}
#Bean
Mapper mapper()
{
return new DozerBeanMapper();
}
public void run(String... args) throws Exception
{
}
public static void main(String[] args) throws Exception
{
SpringApplication.run(Server.class, args);
}
}
Following is my main class
#Configuration
#ComponentScan({ "myproject.business" })
#EnableNeo4jRepositories(basePackages = "myproject")
public class MainWithStructure extends Neo4jConfiguration implements CommandLineRunner
{
#Autowired
private MyService myService;
public MainWithStructure()
{
setBasePackage("myproject");
}
#Bean
SpringRestGraphDatabase graphDatabaseService()
{
return new SpringRestGraphDatabase("http://localhost:7474/db/data");
}
.......
......
public static void main(String[] args) throws Exception
{
FileUtils.deleteRecursively(new File("accessingdataneo4j.db"));
SpringApplication app = new SpringApplication(MainWithStructure.class);
app.setWebEnvironment(false);
app.run(args);
}
}
Following is my Component class
#Component
public class MyService
{
#Autowired
private Mapper mapper; //Fails to autowire org.dozer.Mapper
.....
}
Following is my Controller class
#RestController
#RequestMapping("/rest")
public class MyController
{
#Autowired
private Mapper mapper; //autowire sucess org.dozer.Mapper
}
I got following Exception when I run main class MainWithStructure
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mainWithStructure': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private myproject.business.MyService myproject.main.MainWithStructure.MyService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.dozer.Mapper myproject.business.MyService.mapper; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.dozer.Mapper] 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)}
Following is my project structure
demo_project
src/main/java
---myproject.main
------MainWithStructure.java
------Server.java
---myproject.business
------MyService.java
---myproject.rest
------MyController.java
If I autowire org.dozer.Mapper in Controller, it sucessfuly autowired it. BUT if I autowire org.dozer.Mapper in Component class it fails to autowire.
Why it is failing to autowire org.dozer.Mapper only on Component class?
Please make me correct if I wrong. Thank you :)
Your Server is not in one of the packages that you #ComponentScan, so the Mapper is indeed not a bean. Try removing the explicit package from the #ComponentScan (since everything is in a subpackage of the main class that will pick up all the components).
You can add #SpringBootApplication in your main class which has #ComponentScan
which will scan all your sub components in project.

How to wire or autowire think properly?

I like spring, I like those annotations, save me a lot of time. But it also give me headed. So can someone explain for me about #Autowired plz?
I followed some tutorial and here is what I got:
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'registerController':
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.isad.dao.UserAccountDAO
com.isad.controller.RegisterController.userAccount; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.isad.dao.UserAccountDAO] 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)}
My Pojo:
private int id;
private String username;
private String email;
private String password;
My Dao:
#Repository
#Transactional
public class UserAccountDAOImpl implements UserAccountDAO{
#Autowired
private SessionFactory sessionFactory;
public UserAccount getById(int id) {
return (UserAccount) sessionFactory.getCurrentSession()
.get(UserAccount.class, id);
}
public int save(UserAccount aUser) {
return (Integer)sessionFactory.getCurrentSession().save(aUser);
}
}
My Controller:
#Autowired
private UserAccountDAO userAccount;
#Autowired
private UserAccountFormValidator validator;
#RequestMapping(value="register", method=RequestMethod.POST)
public String registerPage(#ModelAttribute("newUserAccount") UserAccount aUser,
BindingResult result) {
System.out.println("inside register post");
validator.validate(aUser, result);
if( result.hasErrors()) {
return "register";
}
userAccount.save( aUser );
return "../../index";
}
UserAccountFormValidator:
#Component("useraccountFormValidator")
public class UserAccountFormValidator implements Validator{
#Override
public boolean supports(Class<?> arg0) {
return UserAccount.class.isAssignableFrom( arg0 );
}
#Override
public void validate(Object arg0, Errors arg1) {
ValidationUtils.rejectIfEmptyOrWhitespace(arg1, "name", "required");
}
}
The package com.isad.dao of UserAccountDAOImpl is likely not being scanned for Spring beans. Check your Spring configuration.
Make sure your spring config file provide this:
<context:component-scan base-package="com.isad"/>

Resources