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
Related
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
I'm trying to add a Camel rout to a working project with Spring Boot for using MongoDB. I've using Mongo with Spring Boot autoconfigure, and it worked pretty easily.
I was confused about how to specify the bean that Spring Boot generates, but I finally found an answer to a related question on SO that said the name of the bean is "mongo". So I changed my rout to .to("mongodb:mongo?....
No Spring is trying to connect to default parameters, localhost and 72017, etc. So how do I figure out what properties to specify in application.properties to set the connection parameters? The documentation isn't being helpful here.
{Edit: I managed to figure this out. The below works now}
Here are the Maven dependencies I added:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-mongodb</artifactId>
<version>${camel-version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-mongodb-starter</artifactId>
<version>${camel-version}</version>
</dependency>
And here are the additions to my application.properties file
spring.data.mongodb.host=<IP>
spring.data.mongodb.port=27017
spring.data.mongodb.database=dev
spring.data.mongodb.username=test
spring.data.mongodb.password=password
And the Camel route:
package Order;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;
#Component
public class OrderRouter extends RouteBuilder {
#Override
public void configure() {
// Process message
from("jms:topic:order")
.log("JMS Message: ${body}")
.choice()
.when().jsonpath("$.[?(#.type=='partial')]")
.to("mongodb:mongo?database=dev&collection=order&operation=insert");
}
}
Does this mean I need to define a bean when connecting with Camel? Looking at the documentation it seems that it should generate a bean by adding camel-mongodb-starter along with the application.properteis
https://camel.apache.org/components/latest/mongodb-component.html#_spring_boot_auto_configuration
I found the spring bean name, but only by looking around for examples...
spring.data.mongodb
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 developed a micro service in Spring boot and it is deployed in Cloud Foundry. MongoDB is a service created in PCF and it is a replica set type service. The mongodb service is bound to the micro service in PCF. I am using Spring cloud connector to automatically fetch the connection string for the mongodb service when deployed in cloud using the following code.
#Configuration
#Profile("cloud")
public class CloudFoundryDatabaseConfig extends AbstractCloudConfig{
#Bean
public Cloud cloud() {
return new CloudFactory().getCloud();
}
#Bean
public MongoDbFactory mongoFactory() {
return connectionFactory().mongoDbFactory();
}
}
This code is working perfectly fine when the mongoDB service is a standalone type. However if it is a replica set, i get a unknown host exception. Since the mongodb URI contains comma separated host names, it seems to be unresolved.
An example of MongoDB URI below.
"mongodb://username:password#101.23.65.41:28000,101.23.65.43:28000,101.23.65.45:28000/default?authSource=admin"
Error:
com.mongodb.MongoSocketException: mongod-node-0-310d0fd1.mongodb.internal: Name or service not known}, caused by {java.net.UnknownHostException
Pom.xml:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry-connector</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-spring-service-connector</artifactId>
</dependency>
Please help.
I'm trying to set up a simple cloud stream Sink but keep running into the following errors.
I've tried several binders and they all keep giving the same error.
"SEVERE","logNameSource":"org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter","message":"
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method binderAwareRouterBeanPostProcessor in org.springframework.cloud.stream.config.BindingServiceConfiguration required a bean of type '[ Lorg.springframework.integration.router.AbstractMappingMessageRouter;' that could not be found.
Action:
Consider defining a bean of type '[ Lorg.springframework.integration.router.AbstractMappingMessageRouter;' in your configuration.
I'm trying to use a simple Sink to log an incoming message from a kafka topic
#EnableBinding(Sink.class)
public class ReadEMPMesage {
private static Logger logger =
LoggerFactory.getLogger(ReadEMPMesage.class);
public ReadEMPMesage() {
System.out.println("In constructor");
}
#StreamListener(Sink.INPUT)
public void loggerSink(String ccpEvent) {
logger.info("Received" + ccpEvent);
}
}
and my configuration is as follows
# Test consumer properties
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.group-id=testEmbeddedKafkaApplication
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.ByteArrayDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.ByteArrayDeserializer
# Binding properties
spring.cloud.stream.bindings.output.destination=testEmbeddedOut
spring.cloud.stream.bindings.input.destination=testEmbeddedIn
spring.cloud.stream.bindings.output.producer.headerMode=raw
spring.cloud.stream.bindings.input.consumer.headerMode=raw
spring.cloud.stream.bindings.input.group=embeddedKafkaApplication
and my pom
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
TL;DR - check your version of Spring Boot and try upgrading it a few minor revs.
I ran into this problem on a project after upgrading from Spring Cloud DALSTON.RELEASE to Spring Cloud Edgware.SR4 -- it was strange because other projects worked fine but there was a single one that didn't.
After further investigation I realized that the troublemaker project was using Spring Boot 1.5.3.RELEASE and others were using 1.5.9.RELEASE
After upgrading Spring Boot to 1.5.9.RELEASE things seemed to start working