this is my mongo config:
#Configuration
public class MongoConfig {
#Bean
public MongoCustomConversions customConversions() {
return new MongoCustomConversions(Arrays.asList(new OffsetDateTimeReadConverter(), new OffsetDateTimeWriteConverter()));
}
#Bean
public ValidatingMongoEventListener validatingMongoEventListener() {
return new ValidatingMongoEventListener(validator());
}
#Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
}
and:
spring:
data:
mongodb:
uri: mongodb://localhost:27017/my-database
I have noticed that whatever changes I am making to my collection in the Spring Boot service, whether I use repository or MongoOperations, save or find, they are visible only during the lifetime of the Spring Boot service and are NOT visible with command line mongo interface. Also the documents that I add with mongo command line are NOT visible to the spring boot service.
To my knowledge I have only one instance of mongodb, only one is visible in Task manager. I double checked the name of db and collection, too.
What could be the reason?
I have found that the problem was caused by embedded MongoDB:
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>
Despite the scope being test, the embedded server run also for the main configuration. I could observe this behaviour only in eclipse, not in Intellij.
I could solve or at least circumvent the problem by excluding the embedded configuration:
#SpringBootApplication(exclude = EmbeddedMongoAutoConfiguration.class)
public class MyApplication
Related
I'm following a tutorial to create a mild spring boot application. I am running the IntelliJ community edition. I want to connect a docker container running Postgresql to the application. The idea is that there is a person database which has two tables for a name and id. I want to connect the person database with the spring boot app so I can run queries against it.
https://youtu.be/vtPkZShrvXQ?t=4309
I ran a docker-compose in terminal to create the container, then installed the docker extension on IntelliJ. I am new to this so please be patient. I am willing to redo if there are better approaches. I have attached source code for my controller, the link of the tutorial, an image of docker container running in IntelliJ, and an image of my docker-compose.yml file.
#RequestMapping("api/v1/person")
#RestController
public class PersonController {
private final PersonService personService;
#Autowired
public PersonController(PersonService personService) {
this.personService = personService;
}
#PostMapping
public void addPerson(#RequestBody Person person){
personService.addPerson(person);
}
#GetMapping
public List<Person> getAllPeople(){
return personService.getAllPeople();
}
#GetMapping(path="/{id}")
public Person getPersonById(#PathVariable("id") UUID id){
return personService.getPersonById(id)
.orElse(null);
}
#DeleteMapping(path="{id}")
public void deletePerson(#PathVariable("id") UUID id){
personService.deletePerson(id);
}
#PutMapping(path="{id}")
public void updatePerson(#PathVariable("id") UUID id, #RequestBody Person personToUpdate){
personService.updatePerson(id,personToUpdate);
}
}
You have to use Spring Data starter with postgres sql driver
Add following dependencies:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
application.properties:
## default connection pool
spring.datasource.hikari.connectionTimeout=20000
spring.datasource.hikari.maximumPoolSize=5
## PostgreSQL
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres-spring
spring.datasource.password=password
#drop n create table again, good for testing, comment this in production
spring.jpa.hibernate.ddl-auto=create
I created a project following the steps of the sample project at https://github.com/teiid/teiid-spring-boot/tree/master/samples/mongodb and added org.teiid:spring-odata dependency for OData exposure.
I find out that it exposed all collections in the MongoDB database as OData entities by default. Would it possible to configure it to expose specific collections only?
Updated:
You can add following to application.properties,
spring.teiid.data.mongodb.accounts.remoteServerList=localhost:27017
spring.teiid.data.mongodb.accounts.database=sampledb
spring.teiid.data.mongodb.accounts.user=admin
spring.teiid.data.mongodb.accounts.password=admin
spring.teiid.data.mongodb.accounts.authDatabase=admin
spring.teiid.data.mongodb.accounts.importer.excludeTables=.*
where "accounts" is the bean name. See "importer properties"
http://teiid.github.io/teiid-documents/master/content/reference/MongoDB_Translator.html
Then to configure the data source
#Configuration
public class DataSources {
#Bean
public MongoDBConnectionFactory accounts(#Qualifier("config") #Autowired MongoDBConfiguration config) {
return new MongoDBConnectionFactory(new MongoDBTemplate(config));
}
#ConfigurationProperties("spring.teiid.data.mongodb.accounts")
#Bean("config")
public MongoDBConfiguration mongoConfig() {
return new MongoDBConfiguration();
}
}
The above is when strictly talking about exposing MongoDB alone without any other changes.
In my application I am using two data modules (spring-boot-starter-data-jpa and spring-boot-starter-data-redis).
I have a method annotated with #CachPut to store in cache. this method is called once but the actual CachePut operation is happening twice. when I debug there are two proxies created which intercepts the same method.
When I use only one module spring-boot-starter-data-redis it works as expected because there is only one proxy created which intercepts the method having #CachPut annotation.
But as per our requirement our application need to use both the data modules (spring-boot-starter-data-jpa for DB related stuff and spring-boot-starter-data-redis for handling some cache related stuff). If I add spring-boot-starter-data-jpa then the cache operation is getting executed twice (due to multiple proxies).
Is there any way to disable proxy creation with #EnableCaching for jpa module but enable only for redis module.
Code Snippets
Configuration class:
#Configuration
#EnableCaching
public class MyConfiguration {
#Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory, #NotNull RedisCacheProperties properties) {
....
}
}
Dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>1.5.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>1.5.9.RELEASE</version>
</dependency>
CacheProcessor (Interface and Implementation classes)
public interface MyCacheProcessor {
MyData store(final MyData myData);
}
public class MyCacheProcessorImpl implements MyCacheProcessor {
#CachePut(cacheNames = {"my-data"}, key = "#myData.id")
public MyData store(final MyData myData) {
log.debug("storing in redis"); // This is printed only once (but actual cache put operation is happening twice )
return myData;
}
}
yaml configs
spring:
redis:
timeout: 500
host: devserver
port: 26379
datasource:
url: jdbc:h2:mem:testdb;Mode=Oracle;DB_CLOSE_ON_EXIT=FALSE
platform: h2
redis.cache.enabled: true
application:
redis:
cache:
my-data:
ttl: 15m
serializer:
type: org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
handles: com.my.sample.model.MyData
I expect the cache operation should be executed only once even If I use both the data modules. Currently the cache operation is executed twice.
Any guidance would be appreciated.
I am using spring-data-mongodb 1.10.12 with mongo 3.6.4. I recently upgraded from a lower version of mongo, and now my mongo connection pool monitoring is broken because there is no ConnectionPoolStatisticsMBean registered. According to the documentation for that version of mongo "JMX connection pool monitoring is disabled by default. To enable it add a com.mongodb.management.JMXConnectionPoolListener instance via MongoClientOptions"
However, in the xml schema for spring-data-mongo, the clientOptionsType does not allow setting that value, unless I am missing something. Is there any way, with spring-data-mongodb, to turn on the connection pool monitoring through xml?
Here is my xml for the mongo beans
<mongo:mongo-client id="mongo"
host="${mongo.hostname:#{null}}"
replica-set="${mongo.replica.set:#{null}}"
port="${mongo.port}"
credentials="'${mongo.username}:${mongo.password}#${mongo.auth.db.name}?uri.authMechanism=${mongo.auth.mechanism:SCRAM-SHA-1}'"
>
<mongo:client-options connections-per-host="${mongo.connections-per-host:40}"
threads-allowed-to-block-for-connection-multiplier="${mongo.threads-blocked-per-connection:3}"
connect-timeout="${mongo.connection-timeout:10000}"
max-wait-time="${mongo.maxWaitTime:120000}"
socket-keep-alive="${mongo.socketKeepAlive:true}"
socket-timeout="${mongo.socketTimeout:0}"
read-preference="${mongo.read.preference:PRIMARY_PREFERRED}"
write-concern="${mongo.write.concern:ACKNOWLEDGED}"
/>
</mongo:mongo-client>
and my pom dependencies
<properties>
<mongo-version>3.6.4</mongo-version>
<spring-data-version>1.10.12.RELEASE</spring-data-version>
</properties>
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${mongo-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>${spring-data-version}</version>
</dependency>
</dependencies>
It is true that there is no way, through the spring-data-mongodb schema, to add a connection pool listener, but the folks that maintain the repo suggested a solution which is to use a BeanPostProcessor to alter the MongoClientOptions before they are passed to the mongo client like so
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof MongoClientOptions) {
return MongoClientOptions.builder((MongoClientOptions) bean)
.addConnectionPoolListener(new JMXConnectionPoolListener()).build();
}
return bean;
}
Doing so successfully registered ConnectionPoolStatisticsMBeans for me
I tackled the very same challenge. In my case, originally the Spring configuration was done using XML. I have managed to combine the XML configuration with Java configuration, because the Java configuration gives you more flexibility to configure the MongoClientOptions:
#Configuration
public class MongoClientWrapper {
#Bean
public MongoClient mongo()
{
//credentials:
MongoCredential credential = MongoCredential.createCredential("user", "auth-db", "password".toCharArray());
MongoClientOptions options = MongoClientOptions.builder()
.addConnectionPoolListener(new MyConnectionPoolListener())
.build();
return new MongoClient(
new ServerAddress("localhost", 27017), //replica-set
Arrays.asList(credential)
,options
);
}
#Bean
public MongoTemplate mongoTemplate()
{
return new MongoTemplate(mongo(), database);
}
...
}
Hope this helps someone...
In my project, adding the BeanPostProcessor was useless, because the MongoClientOptions Bean was not automatically instantiate.
I had to create Bean manually to add a connection pool listener in my environment:
#Bean public MongoClientOptions myMongoClientOptions() {
return MongoClientOptions.builder().addConnectionPoolListener(new JMXConnectionPoolListener()).build();
}
I have setup a SpringBootAdmin server, and trying to register an application with SpringBootAdmin client. It does not seem to be registering.
Do I neccesarily have to register with Eureka?
How do I debug?
Configuration on adminserver
build.gradle
dependencies {
compile('de.codecentric:spring-boot-admin-server-ui')
compile('de.codecentric:spring-boot-admin-server-ui-login')
compile('de.codecentric:spring-boot-admin-server')
compile('org.springframework.boot:spring-boot-starter-web-services')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
application.properties
spring.application.name=Boot-Admin
server.port=8093
security.user.name=admin
security.user.password=admin
logging.level.de.codecentric.boot.admin.client=DEBUG
logging.level.de.codecentric.boot.admin=DEBUG
App is
#SpringBootApplication
#Configuration
#EnableAdminServer
public class AdminApp {
public static void main(String[] args) {
SpringApplication.run(AdminApp.class, args);
}
}
On the client side,
build.gradle
dependencies {
compile('de.codecentric:spring-boot-admin-starter-client')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-web-services')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
application.properties
server.port=8091
spring.boot.admin.client.enabled=true
spring.boot.admin.url=http://localhost:8093
spring.boot.admin.client.auto-registration=true
spring.boot.admin.username=admin
spring.boot.admin.password=admin
logging.level.de.codecentric.boot.admin.client=DEBUG
Code is
#Configuration
#SpringBootApplication
public class SBACApp {
public static void main(String[] args) {
SpringApplication.run(SBACApp.class, args);
}
}
According to all the Stackoverflow articles and tutorials, this should be adequate.
Even though logging is set on the client side, there seems to be no log-line starting with d.c....
What could I be missing
Any additional knowledge on how to debug this may help.
If you are using spring boot admin 2.0 the the client url property would be
spring.boot.admin.client.url: http://localhost:8093
I would check to see what version you are using and then double check the property names.
In Spring Boot 2.x.x version client url property is different that Spring Boot 1.x.x
spring.boot.admin.client.enabled=true
spring.boot.admin.client.url= http://localhost:8093
spring.boot.admin.client.auto-registration=true
make sure you have other two properties. in my case i was missing auto registration property