MongoDB configuration in Spring Boot and Spring Data REST - spring

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.

Related

Spring looking for PostgreSql driver, but I'm using JTDS

Loading a spring cloud dataflow app fails with this log:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: org.postgresql.Driver
But configuration is:
spring.jpa.database=sybase
spring.datasource.url=jdbc:jtds:sybase://xxx:X000/xxxx;autoCommit=false;appName=dataflow
spring.datasource.username=xx
spring.datasource.password=xxx
spring.datasource.driver-class-name=net.sourceforge.jtds.jdbc.Driver
spring.datasource.hikari.driver-class-name=net.sourceforge.jtdatasource.jdbc.Driver
spring.datasource.hikari.pool-name=datasource-pool
spring.datasource.hikari.connection-timeout=3000
spring.datasource.hikari.maximum-pool-size=2
spring.datasource.hikari.minimum-idle=0
spring.datasource.hikari.connection-test-query=SELECT 1
spring.datasource.hikari.auto-commit=false
spring.datasource.hikari.transaction-isolation=TRANSACTION_READ_COMMITTED
Dependency:
<dependency>
<groupId>net.sourceforge.jtds</groupId>
<artifactId>jtds</artifactId>
<version>1.3.1</version>
</dependency>
PostgreSql is never specified.
Using spring boot 2.3.3
Update:
I think something in spring dataflow context is setting the driver, because it works if I create my own configuration class and don't use spring.datasource prefix:
#Configuration
public class DataSourceConfiguration {
#Bean
#Primary
#ConfigurationProperties("spring.ds")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#ConfigurationProperties("spring.ds.hikari")
public HikariDataSource sybaseDataSource() {
return dataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
}

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 {}

Usage of Spring #ConfigurationProperties gives nullpointer when running tests, JHipster app

I have implemented a simple file upload routine using Spring Boot ConfigurationProperties annotation so I can load the directory from my YAML configuration file:
Service:
#Service
public class FileSystemStorageService implements StorageService {
private final Logger log = LoggerFactory.getLogger(FileSystemStorageService.class);
private final Path pictureLocation;
#Autowired
public FileSystemStorageService(StorageProperties storageProperties) {
pictureLocation = Paths.get(storageProperties.getUpload());
}
And the StorageProperties:
#Component
#ConfigurationProperties("nutrilife.meals")
public class StorageProperties {
private String upload;
public String getUpload() {
return upload;
}
public void setUpload(String upload) {
this.upload= upload;
}
}
In the yaml file I have:
nutrilife:
meals:
upload: /$full_path_to_my_upload_dir
This works perfectly in normal Spring Boot runtime but the problem starts when I try to run my integration tests, it throws the error:
java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fileSystemStorageService' defined in file [/home/mmaia/git/nutrilife/build/classes/main/com/getnutrilife/service/upload/FileSystemStorageService.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.getnutrilife.service.upload.FileSystemStorageService]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:279)
...
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.getnutrilife.service.upload.FileSystemStorageService]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:154)
So basically during tests the YAML file configuration looks like it's not being properly picked up. I am new to Spring. How can I fix it?
try adding the #value annotation :
#Value("upload")
private String upload;
The above answer is valid for application.properties config.
it also works with yaml as well.
You may find your correct correct yaml config here :
24.6 Using YAML instead of Properties

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.

Not an managed type for Spring Data Mongodb

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.

Resources