WebTestClient does not work when using spring-webflux - spring

I'm using Spring webflux via Spring boot 2.0.0.M3. Below is the dependencies of my project,
dependencies {
compile 'org.springframework.boot:spring-boot-starter-actuator',
'org.springframework.cloud:spring-cloud-starter-config',
'org.springframework.cloud:spring-cloud-sleuth-stream',
'org.springframework.cloud:spring-cloud-starter-sleuth',
'org.springframework.cloud:spring-cloud-starter-stream-rabbit',
'org.springframework.boot:spring-boot-starter-data-mongodb-reactive',
'org.springframework.boot:spring-boot-starter-data-redis-reactive',
'org.springframework.boot:spring-boot-starter-integration',
"org.springframework.integration:spring-integration-amqp",
"org.springframework.integration:spring-integration-mongodb",
'org.springframework.retry:spring-retry',
'org.springframework.boot:spring-boot-starter-webflux',
'org.springframework.boot:spring-boot-starter-reactor-netty',
'com.fasterxml.jackson.datatype:jackson-datatype-joda',
'joda-time:joda-time:2.9.9',
'org.javamoney:moneta:1.0',
'com.squareup.okhttp3:okhttp:3.8.1',
'org.apache.commons:commons-lang3:3.5'
compileOnly 'org.projectlombok:lombok:1.16.18'
testCompile 'org.springframework.boot:spring-boot-starter-test',
'io.projectreactor:reactor-test',
'org.apache.qpid:qpid-broker:6.1.2',
'de.flapdoodle.embed:de.flapdoodle.embed.mongo'
}
The app is running well via ./gradlew bootRun or running main app directly.
However I failed to start integration test due to below error.
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
I'm wondering why WebTestClient still tries to use embedded tomcat even though we are using webflux that uses reactive-netty by default.
Is it something misconfiguration or bug of spring boot test?
Below is code snippet of my test case,
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class NoteHandlerTest {
#Autowired
private WebTestClient webClient;
#Test
public void testNoteNotFound() throws Exception {
this.webClient.get().uri("/note/request/{id}", "nosuchid").accept(MediaType.APPLICATION_JSON_UTF8)
.exchange().expectStatus().isNotFound();
}
}

The error of launching tomcat was caused by test dependency org.apache.qpid:qpid-broker:6.1.2, which depends on javax.serlvet-api:3.1 break the tomcat's startup.
Excluding below useless modules to make tomcat launching again,
configurations {
all*.exclude module: 'qpid-broker-plugins-management-http'
all*.exclude module: 'qpid-broker-plugins-websocket'
}

Related

Spring Boot Gradle build fails with "Execution failed for task 'bootWarMainClassName'

I have a multi-project gradle build with Spring Boot structured per default gradle conventions.
root
-- common
-- src/main/java
-- bootproject
-- src/main/java
My current project is to (A) upgrade gradle from 5.x to 7.3.x and (B) use embedded tomcat with Spring Boot.
This is a project that has existed for many years and is Spring Boot but has always been deployed traditionally as a WAR file in Tomcat.
I have upgraded gradle to 7.3.3 following the gradle migration guide and have "common" building correctly (java-library). I am now trying to make "bootproject" build correctly again. I have migrated my build.gradle, and compilation happens correctly now but upon executing 'gradlew sub-project:build' I get the error:
Execution failed for task ':tx-main:bootWarMainClassName'.
java.lang.IllegalArgumentException (no error message)
My ROOT build.gradle is simple:
plugins {
id "org.springframework.boot" version "2.6.3"
}
subprojects {
apply plugin: 'java'
group = 'com.blah'
version = '2.1.1'
repositories {
mavenCentral()
}
There is a library sub-project (common) that builds fine.
The Spring Boot subproject build.gradle is:
plugins {
id 'org.springframework.boot'
id 'io.spring.dependency-management'
}
dependencies {
implementation project(path:':common', configuration:'default')
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation ...
}
The main class was originally set up to make the app conventionally deployed (extends SpringBootServletInitializer), but has been replaced with (taken directly from docs):
package com.blah;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The compilation works, this class appears to be in the build/classpath so I don't understand why Gradle-Spring-Boot is not finding it. I have also tried explicitly identifying the class with the same result.
Unfortunately I find little documentation about multi-project gradle builds so I suspect that is part of the problem. Hopefully someone here can point me in the right direction as to what is wrong.
Thanks
I discovered the issue here. We have custom code in /buildSrc that is apparently causing this.

Junit tests start failing after adding #ComponentScan in the Spring boot application class file

I am using Spring boot version 2.3.3.Release
Junit platform launcher 1.5.2
If I add #ComponentScan under #SpringBootApplication, the tests fail with the error :-
Caused by org.springframework.dao.InvalidDataAccessApiUsageException at RepositoryConfigurationExtensionSupport.java:367
My tests have the config like :-
#ExtendsWith(SpringExtension.class)
#WebMvcTest(value = Abcd.class)
And i use :-
#MockBean for service layer and
#Autowired for MockMvc bean
EDIT 1:
I added the ComponentScan to include an external library. The jar is in a lib folder and i use gradle compile filetree to include it.

Spring Boot Profile Gradle

Based on this post, I run my Spring Boot application with
./gradlew bootRun -Dspring-boot.run.profiles=foo
A component with the profile doesn't run. And I try to verify the active profile with the following code in the root Application class
#Autowired
private Environment environment;
#PostConstruct
void postConstruct(){
String[] activeProfiles = environment.getActiveProfiles();
log.info("active profiles: {}",
Arrays.toString(activeProfiles));
}
The log message output is blank.
What is missing?
-Dspring-boot.run.profiles=foo only works with maven. So it will not work with gradle. You can find informaiton on how to bootrun with gradle here.

How to exclude jersey 1.x dependencies when running tests with gradle

We have a web service project that relies on Netflix's Eureka and it has a dependency on Jersey client 1.x.
Our project is using gradle and in the project we have our src, unit, integration, and functional tests. For our functional tests we have a jar that we import in the testCompile gradle section that wraps a Jersey client to send requests to the web service.
Now my question is how can I get the netflix Jersey client dependency to be ignored in the testCompile so I can use the new Jersey 2.x client for the functional tests?
Build Scripts below:
Main service build script excerpt:
dependencies {
compile 'com.netflix.eureka:eureka-client:1.1.97'
compile 'com.sun.jersey:jersey-bundle:1.18'
testCompile 'some.domain:service-test-client:1.0.1'
}
service test client relevant parts:
dependencies {
compile 'org.glassfish.jersey.core:jersey-client:2.19'
compile 'org.glassfish.jersey.connectors:jeresey-apache-connector:2.19'
}
Relevant parts of the Eureka Client gradle script from github:
ext {
githubProjectName = 'eureka'
awsVersion='1.9.3'
servletVersion='2.5'
jerseyVersion='1.11'
governatorVersion='1.3.3'
archaiusVersion='0.6.5'
blitzVersion='1.34'
mockitoVersion='1.9.5'
junit_version='4.10'
mockserverVersion='3.9.2'
jetty_version='7.2.0.v20101020'
}
dependencies {
compile "com.sun.jersey:jersey-core:$jerseyVersion"
compile "com.sun.jersey:jersey-client:$jerseyVersion"
compile 'com.sun.jersey.contribs:jersey-apache-client4:1.11'
compile 'org.apache.httpcomponents:httpclient:4.2.1'
}
With the above setup I get method not found errors because when the tests are running some of the jersey 1.x classes are taking precedence over the classes brought in with the test-client jar.
You can use gradle dependency monitoring to find out what libraries are bringing in jersey.
./gradlew dependencies
You can pipe that into a file, and less your way into finding out who's bringing in jersey 1.*.
Then, just exclude it from those specifically, and compile your own:
compile("com.example.library:artifactId:x.y.z"){
exclude group:'org.glassfish.jersey', module:jersey-common
}
compile('org.glassfish.jersey.core:jersey-common:2.4.1')
I got same problem with jersey 1.x vs glassfish 2.x with Eureka (but with Spring Cloud). I'm trying this:
compile ("org.springframework.cloud:spring-cloud-starter-eureka:1.0.0.RELEASE")
{
exclude group:'com.sun.jersey', module: 'jsr311-api'
}
But then Eureka doesn't work for me...
I think I will try to switch to Eureka 2.0 with different jersey, but without spring cloud:
https://github.com/Netflix/eureka/wiki/Eureka-2.0-Architecture-Overview
http://mvnrepository.com/artifact/com.netflix.eureka check Eureka2 dependencies
maybe you can use them?

Importing RestAssured in Spring Boot Test

I have developed a Spring Boot Application.
I am using RestAssured to test the same
following are the dependencies in build.gradle
dependencies {
compile("org.springframework.boot:spring-boot-starter-actuator")
compile("org.springframework.boot:spring-boot-starter-aop")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("org.springframework.boot:spring-boot-starter-mail")
compile("org.springframework.boot:spring-boot-starter-security")
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity3:2.1.2.RELEASE")
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-freemarker")
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
runtime("mysql:mysql-connector-java")
testCompile("org.springframework.boot:spring-boot-starter-test")
testCompile('com.jayway.restassured:rest-assured:2.4.1')
}
I am facing a problem while importing RestAssured in a Integration Test class for Spring Boot
import static com.jayway.restassured.RestAssured.*;
When I try to run the application using gradle I am getting the following error
Error:(15, 37) java: package com.jayway.restassured does not exist
Why is this problem and how to solve it ?

Resources