connect mongohq or mongolab using spring framework - spring

i try to connect to mongohq using spring. i got some information from heroku but while connecting with that code MongoURI class are deprecated .
I used spring-data-mongodb version 1.2.0.RELEASE. and mongo-java-driver - 2.11.0
can any one tell how to connect to mongohq or mongolab using spring

Hear is the code..
#Configuration
public class SpringConfig {
#Bean
public DB getDb() throws UnknownHostException, MongoException {
String uri="mongodb://user:password#id.mongolab.com:53178/db";
MongoClientURI mongoClientURI=new MongoClientURI(uri);
MongoClient mongoClient=new MongoClient(mongoClientURI);
DB db=mongoClient.getDB(mongoClientURI.getDatabase());
db.authenticate(mongoClientURI.getUsername(),mongoClientURI.getPassword());
return db;
}
}

As you can read in the MongoURI documentation
public class MongoURI
extends Object
Represents a URI which can be used to create a Mongo instance. The URI describes the hosts to be used and options.
This class has been superseded by MongoClientURI, and may be deprecated in a future release.
So MongoClientURI is your answer

If you use mongodb with Spring Data Mongodb you can use a configuration as described in http://docs.spring.io/spring-data/data-mongo/docs/1.4.1.RELEASE/reference/html/mongo.core.html#mongo.mongo-db-factory-java
It will finally look like :
#Configuration
public class MongoHQConfiguration {
public #Bean MongoDbFactory mongoDbFactory() throws MongoException, UnknownHostException {
return new SimpleMongoDbFactory(new MongoURI(System.getenv("MONGOHQ_URL")));
}
public #Bean MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory());
}
}

If you are using Spring Boot, the class "MongoProperties" is just waiting for an external configuration:
With "heroku config" you can see properties already defined - there will be a "MONGOLAB_URI" if MongoLab was added to your application.
Just define: heroku config:set spring.data.mongodb.uri=< MONGOLAB_URI >. Done.

Related

Programmatic RedissonClient in Spring boot project

I am trying to implement Hibernate second level caching in a Spring boot project using Redisson.
I have followed this blog as a reference
https://pavankjadda.medium.com/implement-hibernate-2nd-level-cache-with-redis-spring-boot-and-spring-data-jpa-7cdbf5632883
Also i am trying to initialize the RedissionClient programmatically and not through declaratively /through a config file
Created a spring bean to be initialized which should create the RedissonClient instance.
#Configuration
#Lazy(value = false)
public class RedissonConfig {
#Bean
public RedissonClient redissionClient() {
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
return Redisson.create(config);
}
}
However this bean is never intialized and i get the following error while application startup.
Caused by: org.hibernate.cache.CacheException: Unable to locate Redisson configuration
at org.redisson.hibernate.RedissonRegionFactory.createRedissonClient(RedissonRegionFactory.java:107) ~[redisson-hibernate-53-3.12.1.jar:3.12.1]
at org.redisson.hibernate.RedissonRegionFactory.prepareForUse(RedissonRegionFactory.java:83) ~[redisson-hibernate-53-3.12.1.jar:3.12.1]
It seems Spring boot Hibernate still trying to load the Redisson config through a config file.
is it possible to load the Redission config in spring boot programmatically ?
Best Regards,
Saurav
I just did exactly this, here is how:
you need a custom RegionFactory that is similar to the JndiRedissonRegionFactory but gets its RedissonClient injected somehow.
an instance of this Class, fully configured, is put into the hibernate-properties map. Hibernates internal code is flexible: if the value of hibernate.cache.region.factory_class is a string it is treated as a FQDN. If it is an instance of Class<?>, it will be instantiated. If it is an Object, it will be used.
Spring offers a rather simple way to customize hibernate properties with a bean:
#AutoConfiguration(after = RedissonAutoConfiguration.class, before = JpaAutoConfiguration.class)
#ConditionalOnProperty("spring.jpa.properties.hibernate.cache.use_second_level_cache")
public class HibernateCacheAutoConfiguration {
#Bean
public HibernatePropertiesCustomizer setRegionFactory(RedissonClient redisson) {
return hibernateProperties -> hibernateProperties.put(AvailableSettings.CACHE_REGION_FACTORY, new SpringBootRedissonRegionFactory(redisson));
}
}
My RegionFactory is really simple:
#AllArgsConstructor
public class SpringBootRedissonRegionFactory extends RedissonRegionFactory {
private RedissonClient redissonClient;
#Override
protected RedissonClient createRedissonClient(Map properties) {
return redissonClient;
}
#Override
protected void releaseFromUse() {
}
}
I used the redisson-starter to get a RedissonClient, hence the reference to RedissonAutoConfiguration, but you could just create an instance by hand.
It is possible, but then you need to provide a custom implementation of RegionFactory to Hibernate, which can extends RedissonRegionFactory but uses your own client instance.

Application failed to start after spring boot version upgrade from 2.1.18.RELEASE to 2.2.0.RELEASE

When we upgrade the spring-boot-starter-parent version from 2.1.8.RELEASE to 2.2.0.RELEASE, the application is not loading few beans. Due to this, application is failing. #PostConstuct is not able to add BCFIPS Provider in security provider.
#Configuration
#Slf4j
#ComponentScan(basePackages = "com.xxx.yyy.ekms.sdk")
#ConditionalOnProperty(name = "ekms.enabled", havingValue = "true")
public class EKMSClientSdkConfiguration extends ClientConfiguration
{
#PostConstruct
public void addSecurityProvider()
{
Security.addProvider(new BouncyCastleFipsProvider());
}
#Bean
public ApiClientBuilder apiClientBuilder()
{
return new DefaultApiClientBuilder();
}
}
Also, apiClientBuilder bean is not getting created.
The EKMSClientSdkConfiguration is extending ClientConfiguration, which is coming as part of another application jar. This class is not having any annotation.
public abstract class ClientConfiguration {
public ClientConfiguration()
{
}
public abstract void addSecurityProvider();
#Bean
public EKMSClient restClient() {
return new EKMSRestClientImpl(this.apiClient());
}
#Bean
public ApiClient apiClient() {
return Configuration.getDefaultApiClient();
}
}
In our case, EKMSClientSdkConfiguration bean is not getting created and the #PostConstruct is also not getting executed.
I went through the Spring Boot 2.2.RELEASE notes which is pointing to Spring Framework 5.2 upgrade guide. Here, I learned that spring boot 2.2.0 RELEASE is using Spring framework 5.2. In Spring framework 5.2, we have many changes.
It looks like this is the root cause of bean not getting loaded, but I am not sure about it.
Any help will be appreciated. Let me know if additional information is needed.
I found spring.main.lazy-initialization=true property in my application which was causing the above issue. When I removed it from the application.properties, This issue is resolved. This is the major change which was introduced in 2.2.0.RELEASE of spring boot

Cassandra Schema Migration for Java in Spring Boot

I use Cassandra Schema Migration library to initialize database whenever run project. By the tutorial :
Database database = new Database(cluster, "nameOfMyKeyspace");
MigrationTask migration = new MigrationTask(database, new MigrationRepository());
migration.migrate();
Where should I put above script to :
in SpringBootApplication or Cassandra Config or something else?
How to keep and check the version of database? Is there any tutorial for this library?
You can add a CommandLineRunner class which will run at start of application. Something like this :
#Component
#Slf4j
public class AppStartupRunner implements CommandLineRunner {
#Autowired
Cluster cluster;
#Autowired
private Environment environment;
#Override
public void run(String...args) throws Exception {
log.info("Starting DB Migration");
Database database = new Database(cluster, environment.getProperty("cassandra.keyspace"));
MigrationTask migration = new MigrationTask(database, new MigrationRepository("resources/cassandra/migration"));
migration.migrate();
log.info("DB Migration Complete");
}
}
Hope this helps.

How to Replace RemoteServer() when upgrading to Spring Data 4.2+?

In upgrading to Neo 3.2.3 (from Neo 2.5), I've had to upgrade my Spring Data dependency. The main reason for me upgrading is to take advantage of Neo's new Bolt protocol. I bumped the versions (using maven pom.xml), and I'm having issues with one change in particular -- how to set up the scaffolding for Sessions and the RemoteServer configuration.
org.springframework.data.neo4j.server.RemoteServer has been removed from the SD4N api, breaking my code and I'm not sure how to get things to compile again. I've tried a number of sources online, with little success. Here's what I've read:
Neo4j 3.0 and spring data
https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#_spring_configuration
https://graphaware.com/neo4j/2016/09/30/upgrading-to-sdn-42.html
None of these resources quite explain how to refactor the Spring Configuration (and its clients) to use whatever thing replaces the RemoteServer Object.
How do I connect to my Neo database with Spring Data Neo4J, given a url, username, and password? . Bonus points for explaining how these interrelate to Sessions and SessionFactorys.
The configuration should look like this:
#Configuration
#EnableNeo4jRepositories(basePackageClasses = UserRepository.class)
#ComponentScan(basePackageClasses = UserService.class)
static class Config {
#Bean
public SessionFactory getSessionFactory() {
return new SessionFactory(configuration(), User.class.getPackage().getName());
}
#Bean
public Neo4jTransactionManager transactionManager() throws Exception {
return new Neo4jTransactionManager(getSessionFactory());
}
#Bean
public org.neo4j.ogm.config.Configuration configuration() {
return new org.neo4j.ogm.config.Configuration.Builder()
.uri("bolt://localhost")
.credentials("username", "password")
.build();
}
}
SessionFactory and Session are described here
Please comment about what's unclear in the docs.

Spring Mongodb: How to configurer mongoDB with MongoClientFactoryBean

When configuring MongoDB in Spring, the reference sais:
register MongoDB like this:
#Configuration
public class AppConfig {
/*
* Use the standard Mongo driver API to create a com.mongodb.Mongo instance.
*/
public #Bean Mongo mongo() throws UnknownHostException {
return new Mongo("localhost");
}
}
pollutes the code with the UnknownHostException checked exception. The use of the checked exception is not desirable as Java based bean metadata uses methods as a means to set object dependencies, making the calling code cluttered.
so Spring proposes
#Configuration
public class AppConfig {
/*
* Factory bean that creates the com.mongodb.Mongo instance
*/
public #Bean MongoFactoryBean mongo() {
MongoFactoryBean mongo = new MongoFactoryBean();
mongo.setHost("localhost");
return mongo;
}
}
But unfortunately since Spring-Data-MongoDB 1.7 MongoFactoryBean has been deprecated and replaced by MongoClientFactoryBean.
So
#Bean
public MongoClientFactoryBean mongoClientFactoryBean() {
MongoClientFactoryBean factoryBean = new MongoClientFactoryBean();
factoryBean.setHost("localhost");
return factoryBean;
}
Then it's time to configure MongoDbFactory which has only one implementation SimpleMongoDbFactory. The SimpleMongoDbFactory has only two initializer not deprecated one of which is SimpleMongoDbFactory(MongoClient, DataBase).
But MongoClientFactoryBean can only return type of Mongo instead of MongoClient.
So, am I missing something to make this pure Spring configuration work?
Yes it returns a Mongo :-(
But as MongoClient extends Mongo that'll be ok anyway, just #Autowire the bean as a Mongo
#Autowired
private Mongo mongo;
Then use it
MongoOperations mongoOps = new MongoTemplate(mongo, "databaseName");
Do you really need the SimpleMongoDbFactory ? See this post.
In my case, I'm using the following code to create MongoTemplate. I'm using MongoRespository. As it only needs MongoTemplate I need to create the MongoTemplate bean only.
#Bean
public MongoTemplate mongoTemplate() throws Exception {
MongoClient mongoClient = new MongoClient("localhost");
MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClient, "kyc_reader_test");
return new MongoTemplate(mongoDbFactory);
}
In my configuration file, I've added
#EnableMongoRepositories(basePackages = "mongo.repository.package.name")

Resources