I started playing with testcontainers and at the beginning of my journey I faced some issue (below). I did similar thing for mysql db and it worked fine. Do I miss some mongo specific config? According to [docs][1] there is not much to do.
Thanks in advance for any tips / examples.
com.mongodb.MongoSocketOpenException: Exception opening socket
at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:70) ~[mongodb-driver-core-3.11.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:128) ~[mongodb-driver-core-3.11.2.jar:na]
at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:117) ~[mongodb-driver-core-3.11.2.jar:na]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
My code:
gradle.build
testImplementation "org.testcontainers:spock:1.14.3"
testImplementation "org.testcontainers:mongodb:1.14.3"
application.properties
spring.data.mongodb.uri=mongodb://127.0.0.1:27017/test
test
#Testcontainers
class TestContainersExample extends IntegrationSpec {
#Shared
MongoDBContainer mongoDb = new MongoDBContainer()
def "setup"() {
mongoDb.start()
mongoDb.waitingFor(Wait.forListeningPort()
.withStartupTimeout(Duration.ofSeconds(180L)));
}
//test case
}
Testcontainers will map the MongoDB server port to a random port on your machine. That's why you can't hardcode spring.data.mongodb.uri=mongodb://127.0.0.1:27017/test in your property file.
A basic setup with JUnit 5 and Spring Boot >= 2.2.6 can look like the following
#Testcontainers
public class MongoDbIT {
#Container
public static MongoDBContainer container = new MongoDBContainer(DockerImageName.parse("mongo:5"));
#DynamicPropertySource
static void mongoDbProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.mongodb.uri", container::getReplicaSetUrl);
}
}
If you are using a different JUnit or Spring Boot version, take a look at the following guide for the correct Testcontainers setup.
Related
I am trying to build my service as GraalVM native image using Spring and buildpacks. My application is Spring Data REST app talking to PostgreSQL database. There is nothing unusual in the code. The image builds with no issues and runs outside of Docker container, but when I am trying to run the generated GraalVM container I am getting an error:
Description:
Native reflection configuration for org.hibernate.dialect.PostgreSQLDialect is missing.
The exception is
Caused by: java.lang.ClassNotFoundException: org.hibernate.dialect.PostgreSQLDialect
at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:71) ~[na:na]
at java.lang.Class.forName(DynamicHub.java:1319) ~[.....:na]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:130) ~[na:na]
My application.yml:
---
spring:
config:
activate:
on_profile: local
datasource:
url: jdbc:postgresql://localhost:5432/test
username: postgres
password: 1234
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
use-new-id-generator-mappings: false
ddl-auto: none
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
javax:
persistence:
validation:
mode: none
I know that Spring native image support still has issues, I am just wondering if the problem is on my side.
There now is a way to solve this for postgres with the current version of Spring Native using version spring native hints.
Native Hints
This turns out to be simple to implement using an annotation. See example below...
package com.margic.serverless.data;
import org.hibernate.dialect.PostgreSQL95Dialect;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.nativex.hint.TypeHint;
#SpringBootApplication
#TypeHint(types = PostgreSQL95Dialect.class, typeNames = "org.hibernate.dialect.PostgreSQLDialect")
public class DataApplication {
public static void main(String[] args) {
SpringApplication.run(DataApplication.class, args);
}
}
The reason is Spring native support issues: The following dependencies are not known to work with Spring Native: ..., Rest Repositories, ...
I have Spring Boot application with kafka and jpa in it. I am using h2 as my in-memory database. For each test class execution, I don't want kafka to come up for each test class. I have 2 test classes, one is KafkaConsumerTest and another one is JPATest. KafkaConsumerTest is annotated with #SpringBootTest and it perfectly loads the entire application and passes all the test. However, for JPATest, I don't want to bring up the entire application and just few desired context to test out JPA related changes. When I do that, it is throwing the following exception.
Caused by: java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
at com.zaxxer.hikari.HikariConfig.validate(HikariConfig.java:958)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:109)
at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:138)
at org.eclipse.persistence.sessions.DatasourceLogin.connectToDatasource(DatasourceLogin.java:172)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.setOrDetectDatasource(DatabaseSessionImpl.java:233)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.loginAndDetectDatasource(DatabaseSessionImpl.java:815)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:256)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:769)
I am passing the datasource with jdbcUrl in my application.yml file
src/test/resources/application.yml
spring:
datasource:
jdbcUrl: jdbc:h2:mem:mydb
url: jdbc:h2:mem:mydb
driverClassName: org.h2.Driver
username: sa
kafka:
bootstrap-servers: ${spring.embedded.kafka.brokers}
KafkaConsumerTest.java
#RunWith(SpringRunner.class)
#SpringBootTest (classes = Application.class)
#DirtiesContext
#EmbeddedKafka(partitions = 1,
topics = {"${kafka.topic}"})
public class KafkaConsumerTest {
JpaTest.java
#RunWith(SpringRunner.class)
#ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class, classes = {JPAConfiguration.class})
public class NotificationServiceTest {
I tried putting loader as AnnotationConfigContextLoader.class but it gave me the same error. I tried specifying application.yml exclusively using TestPropertyResource but still the same error.
#TestPropertyResource(locations = {"classpath:application.yml"})
I think I am not able to load the context properly here and application.yml file is not able to pick or parse values here.
Any suggestions on how to resolve this.
I am able to solve the issue. The reason of this issue was spring context was not getting loaded properly for other tests as I was not using #SpringBootTest. How I bypassed the error and also loading the spring boot context only for one time was to create a base class like this.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Application.class)
#DirtiesContext
#EmbeddedKafka(partitions = 1,
topics = {"${kafka.topic}"})
public abstract class AbstractSpringBootTest {
}
Now every test class has to extend this class as per the following code. This way spring test will be loaded once only provided the context doesn't get changed during the tests run.
public class MyTest extends AbstractSpringBootTest {
Posting the solution which worked for me for other people's reference.
Now I'm trying to create Message Service function with kafka to use spring-cloud-stream-bind-kafka, but didn't work so well.
Configuration:
spring boot 1.4.2
build.gradle:
compile "org.springframework.cloud:spring-cloud-stream:2.0.1.RELEASE"
compile "org.springframework.cloud:spring-cloud-stream-binder-kafka:2.0.1.RELEASE"
code:
#EnableBindings(MessagePublish.class)
class MessageConfiguration {
}
interface MessagePublish {
#Output("test")
MessageChannel publish();
}
class TestService {
#Autowired
MessagePublish messagePublish;
public void doSomething() {
// do something
messagePublish.publish().send(MessageBuilder.withPayload("test").build());
}
}
It failed when I start the project with this error log
Caused by: org.springframework.boot.autoconfigure.condition.OnBeanCondition$BeanTypeDeductionException: Failed to deduce bean type for org.springframework.cloud.stream.config.BindingServiceConfiguration.bindingService
....
Caused by: java.lang.ClassNotFoundException: org.springframework.integration.support.converter.ConfigurableCompositeMessageConverter
I'm suspecting my spring boot version. It's so low version.
I think spring-cloud-stream-binder-kafka can't be used under spring boot 2.0 version or other reasons.
I don't know how can I do and how can I explore this situation...
If you give me a little advice, I really appreciate you.
If you are using Spring Boot 1.4.x version then you should use the Spring Cloud Camden release train.
https://github.com/spring-projects/spring-cloud/wiki/Spring-Cloud-Camden-Release-Notes
In particular, you should use the following versions:
compile "org.springframework.cloud:spring-cloud-stream:1.1.2.RELEASE"
compile "org.springframework.cloud:spring-cloud-stream-binder-kafka:1.1.2.RELEASE"
I am trying to develop web application using SpringBoot and Postgres Database. However, on connecting to the application, I am getting error "Failed to determine a suitable driver class"
As per advise in older posts, I have tried using driver of different version of jdbc and also tried creating bean for NamedParameterJdbcTemplate manually. I also validated that libraries are present and is accessible from Java code and those are present in classpath. But its still giving the same issue.
I am using gradle to import all jars into build path.
Here is the git repository for the code:
https://github.com/ashubisht/sample-sbs.git
Gradle dependency code:
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-websocket")
compile("org.springframework.boot:spring-boot-starter-jdbc")
//compile("org.postgresql:postgresql")
compile("org.postgresql:postgresql:9.4-1206-jdbc42")
testCompile("org.springframework.boot:spring-boot-starter-test")
testCompile group: 'junit', name: 'junit', version: '4.12'
}
Code for building Bean
#Configuration
#PropertySource("classpath:application.properties")
public class Datasource {
#Value("${db.driverClassName}")
private String driverClass;
#Value("${db.url}")
private String url;
#Value("${db.username}")
private String username;
#Value("${db.password}")
private String password;
#Bean
public NamedParameterJdbcTemplate namedParameterJdbcTemplate() throws Exception{
System.out.println(driverClass+" "+ url+" "+username+" "+password);
DriverManagerDataSource source = new DriverManagerDataSource();
source.setDriverClassName(driverClass);
source.setUrl(url);
source.setUsername(username);
source.setPassword(password);
NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(source);
return namedParameterJdbcTemplate;
}
}
Here is application.properties
server.port=8086
#spring.datasource.driverClassName=org.postgresql.Driver
#spring.datasource.url= jdbc:postgresql://localhost:5432/testdb
#spring.datasource.username=postgres
#spring.datasource.password=password
#spring.datasource.platform=postgresql
#spring.jpa.hibernate.ddl-auto=create-drop
db.driverClassName=org.postgresql.Driver
db.url=jdbc:postgresql://localhost:5432/testdb
db.username=postgres
db.password=password
The issue is resolved by creating two beans. Separate bean is created for DataSource and NamedParameterJdbcTemplate.
#Bean
public DataSource dataSource(){
System.out.println(driverClass+" "+ url+" "+username+" "+password);
DriverManagerDataSource source = new DriverManagerDataSource();
source.setDriverClassName(driverClass);
source.setUrl(url);
source.setUsername(username);
source.setPassword(password);
return source;
}
#Bean
public NamedParameterJdbcTemplate namedParameterJdbcTemplate(){
NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(this.dataSource());
return namedParameterJdbcTemplate;
}
For me the issue was in a miss-spell for postgresSql
its only one s,
replace
spring.datasource.url=jdbc:postgres://localhost:5432/databaseName
spring.datasource.url=jdbc:postgressql://localhost:5432/databaseName
with
spring.datasource.url=jdbc:postgresql://localhost:5432/databaseName
also check the same thing on hibernate dialect,
replace PostgresSQLDialect
with PostgreSQLDialect
Had the same problem.
The solution for me was to change application.properties file extension into application.yml
For me the error was
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put
it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
and the issue was missing profile
so I added the following in the classpath and it worked
spring.profiles.active=dev
Please try it
spring.r2dbc.url=r2dbc:postgresql://ip:port/datafeed?currentSchema=user_management
spring.r2dbc.username=username
spring.r2dbc.password=12345
spring.r2dbc.driver=postgresql
Hope to help you!
I got the same error. It happens when you install sts version 3.
I found the solution to this problem by doing trial & error method.
This error is occured due to the non-availability of the connection between Application Properties & the server. I got to know by changing the port number in the application Properties to 9090, later then while running the application the console showed the default port number 8080.
Thus you should maven clean and maven build your Spring Boot Application.
After the above step, you run your application normally as spring boot application, the database will get connected and the application will get started.
I am using spring boot 1.3.x and trying to setup some integration tests using #WebIntegrationTest(randomPort=true) and TestRestTemplate.
few problems that I faced initially -
#Autowired TestRestTemplate testRestTemplate; did not work so , had to go with TestRestTemplate testRestTemplate = new TestRestTemplate();
then , #Value("${local.server.port}") also did not work. it threw exception that it cannot be resolved. so instead had to do this -
#Autowired Environment environment;
and in the #Test method tried to get the port from the environment but all i got is null. so that also did not work.
then changed the port to 8080 by using application.properties and using only #WebIntegrationTest and manually setup the url for TestRestTemplate.
after doing all this, I am getting Connection Refused error now.
pls help. spring documentation is not helping .
thanks