Quarkus dependency injection failing with bean from Gradle Library Module - gradle

I´m trying to get dependency injection working in my multi-module project where I want to inject a bean from a library module. However, it´s failing because it cannot find the bean.
project root settings.gradle
pluginManagement {
repositories {
mavenLocal()
mavenCentral()
gradlePluginPortal()
}
plugins {
id 'io.quarkus' version "${quarkusPluginVersion}"
}
}
include ':service-module'
include ':library-module'
service-module build.gradle
Tried compile, as well as implementation
dependencies {
compile project(":library-module")
// implementation project(":library-module")
}
Bean from library-module
import javax.enterprise.context.ApplicationScoped;
#ApplicationScoped
public class LibraryBean {
public void hello() {
System.out.println("Hello");
}
}
service-module where injection happens
#ApplicationScoped
public class Application {
#Inject
LibraryBean libraryBean;
}
Stacktrace
Unsatisfied dependency for type com.mylibrary.LibraryBean and
qualifiers [#Default]
- java member: com.myservice.Application#LibraryBean
- declared on CLASS bean [types=[com.myservice.Application, java.lang.Object], qualifiers=[#Default, #Any],
target=com.myservice.Application]
I´m not sure if this issue is Quarkus-related or a general problem that exists with CDI and Gradle modules.
How can I make the DI working accross modules?

Do you have a beans.xml file in your library module? See this question/answer for more info: https://stackoverflow.com/a/55513723/742081

Related

Error while trying to get build script read the java file - Could not resolve all artifacts for configuration ':classpath'

I'm trying to follow this by adding my own custom java file into the classpath
https://github.com/gigaSproule/swagger-gradle-plugin#model-converters
This is shown in the example above
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.custom:model-converter:1.0.0'
}
}
...
swagger {
apiSource {
...
modelConverters = [ 'com.custom.model.Converter' ]
}
}
This is my code
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("com.test.app.profile.component.MyOpenApiCustomiser:1.0.0")
}
}
swagger {
apiSource {
...
modelConverters = [ 'com.test.app.profile.component.MyOpenApiCustomiser' ]
}
}
This is the error I'm getting
A problem occurred configuring root project 'profile'.
> Could not resolve all artifacts for configuration ':classpath'.
> Could not find com.test.app.profile.component.MyOpenApiCustomiser:1.0.0:.
Required by:
project :
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
I tried removing 1.0.0
Caused by: org.gradle.api.IllegalDependencyNotation: Supplied String module notation 'com.test.app.profile.component.MyOpenApiCustomiser' is invalid. Example notations: 'org.gradle:gradle-core:2.2', 'org.mockito:mockito-core:1.9.5:javadoc'
Not sure how I would get my build script to the use the MyOpenApiCustomiser in my spring boot application
Is there any other way or how to fix this?
The classpath dependency given in the buildscript.dependencies {} block needs to be a external library, given in the standard group:modulde:version notation; in the example from github project it's "com.custom : model-converter : 1.0.0" ( it's a "fake" library, does not really exist in maven central repo, it's just an example)
In your case, it seems you try to refer your class MyOpenApiCustomiser as the classpath library , which cannot work. It needs to be a real library.
If you want to use your own Converter, you'll need to implement it in another library/module, publish it to a private repository and then consume it in your buildscript classpath.
Another simpler way, would be to implement this converter as a class within the buildSrc project: these classes will then be automatically available in your build script classpath, and you can use it in the apiSource configuration.
Sample:
In your buildSrc project
build.gradle
plugins {
id("java")
}
repositories {
mavenCentral()
}
dependencies {
implementation "io.swagger:swagger-core:1.6.2"
}
Your custom ModelConverter class goes under src/main/java, e.g. com.sample.MyCustomConverter
In your root build.gradle script:
You can reference your MyCustomConverter class, it's already available in the script classpath, no need to define a classpath dependency in buildscript
swagger {
apiSource {
modelConverters = [ 'com.sample.MyCustomConverter' ]
// ....

spring-cloud-stream sample projects raises NoSuchBeanDefinitionException of KafkaStreamsFunctionProcessor

I'm trying to touch spring-cloud-stream, and creating a sample project of the official blog.
Implementation is totally same as the article.
#SpringBootApplication
public class SimpleConsumerApplication {
#Bean
public java.util.function.Consumer<KStream<String, String>> process() {
return input ->
input.foreach((key, value) -> {
System.out.println("Key: " + key + " Value: " + value);
});
}
}
I've selected Cloud Stream and Spring for Apache Kafka Stream on Spring initializr, and added ShadowJar. Now my build.gradle is like this.
plugins {
id 'org.springframework.boot' version '2.4.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'com.github.johnrengelman.shadow' version '6.1.0'
}
group = 'com.lipsum'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
jar {
manifest {
attributes('Main-Class': 'com.lipsum.kafkastream.KafkastreamApplication')
}
}
shadowJar {
archiveBaseName.set('kafka-stream-practice')
archiveClassifier.set('')
archiveVersion.set('')
}
repositories {
mavenCentral()
}
ext {
set('springCloudVersion', "2020.0.2")
}
dependencies {
implementation 'org.apache.kafka:kafka-streams'
implementation 'org.springframework.cloud:spring-cloud-stream'
implementation 'org.springframework.cloud:spring-cloud-stream-binder-kafka-streams'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
test {
useJUnitPlatform()
}
I execute the uber jar, but springboot application fails to recognize the bean.
$ java -jar kafka-stream-practice.jar --spring.cloud.stream.bindings.process-in-0.destination=kafka-stream-practice
...
22:47:21.162 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'kafkaStreamsFunctionProcessorInvoker' defined in class path resource [org/springframework/cloud/stream/binder/kafka/streams/function/KafkaStreamsFunctionAutoConfiguration.class]: Unsatisfied dependency expressed through method 'kafkaStreamsFunctionProcessorInvoker' parameter 1; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.stream.binder.kafka.streams.KafkaStreamsFunctionProcessor' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.stream.binder.kafka.streams.KafkaStreamsFunctionProcessor' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
I don't think the implementation has any problems. Do I miss some dependencies?
I tried a quick maven project from the initialize and it starts fine. There was a known bug on the last release (3.0.11) which was fixed since then on the snapshot. You can fix the issue by adding the boot actuator dependency to the project or by upgrading the binder to the latest snapshot. Could you try the maven approach? If the problem still persists, please share a reproducible sample, and then we will take a look.
It works after removing shadowJar and instead uses bootJar task of Spring Boot Gradle plugin.

Error creating bean with name 'requestMappingHandlerMapping' with kotlin suspend function in spring-boot

spring-boot version : 2.2.6.RELEASE
kotlin version: 1.3.71
kotlin coroutine version: 1.3.5
I'm trying to used suspended function in a controller in spring boot. Here is the official doc that shows an example.
#RestController
#RequestMapping("/account/v1")
class UserAccountResourceV1 {
#GetMapping("/username-taken", produces = [MediaType.TEXT_PLAIN_VALUE])
suspend fun userNameTaken(): String {
return "yes"
}
}
I've added required dependencies in build.gradle.kts:
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-jersey")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
developmentOnly("org.springframework.boot:spring-boot-devtools")
testImplementation("org.springframework.boot:spring-boot-starter-test") {
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
}
implementation(group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version = "1.3.2")
}
It breaks in runtime throwing this err:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Unsupported suspending handler method detected: public java.lang.Object com.example.user.service.resources.UserAccountResourceV1.userNameTaken(kotlin.coroutines.Continuation)
complete stderr is here.
Need some help in figuring out what is wrong with my implementation.
Figured out the solution.
implementation("org.springframework.boot:spring-boot-starter-web")
needed to be replaced with
implementation("org.springframework.boot:spring-boot-starter-webflux")
Basically spring-boot-starter-webflux brings support for suspened functions.

Gradle 5.0: java.lang.String cannot be cast to class groovy.lang.Closure (lombok issue)

I am encountering error during Gradle 5.0 upgrade (from 4.10.2) and have isolated the code to the following block:
dependencyManagement {
dependencies {
compileOnly "org.projectlombok:lombok:1.18.2"
testCompileOnly "org.projectlombok:lombok:1.18.2"
annotationProcessor "org.projectlombok:lombok:1.18.2"
testAnnotationProcessor "org.projectlombok:lombok:1.18.2"
dependency "com.google.guava:guava:$guavaVersion"
dependency "mysql:mysql-connector-java:$mysqlversion"
dependency "com.google.inject:guice:${guiceVersion}"
dependency "org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.1.1.RELEASE"
}
imports {
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
mavenBom "com.amazonaws:aws-java-sdk-bom:${awsVersion}"
}
}
Without the lombok lines, the code works with no issue.
dependencyManagement {
dependencies {
dependency "com.google.guava:guava:$guavaVersion"
dependency "mysql:mysql-connector-java:$mysqlversion"
dependency "com.google.inject:guice:${guiceVersion}"
dependency "org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.1.1.RELEASE"
}
imports {
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
mavenBom "com.amazonaws:aws-java-sdk-bom:${awsVersion}"
}
}
The error is class java.lang.String cannot be cast to class groovy.lang.Closure (java.lang.String is in module java.base of loader 'bootstrap'; groovy.lang.Closure is in unnamed module of loader org.gradle.internal.classloader.VisitableURLClassLoader #675d3402)
I am changing the way lombok is declared due to changes in Gradle 5 annotation processing.
In the dependencies block under dependencyManagement there should not be any concrete dependency declaration eg. compileOnly, testCompileOnly etc. Only dependency is allowed as it is where you define all the - well - dependencies with the proper version for later use in the sub-projects.

Spring boot Jar to war

I am trying to change the spring music application (https://github.com/cloudfoundry-samples/spring-music) from jar to war file to test in Liberty.
I did the following change
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
and also build.gradle
apply plugin: 'war'
dependencies {
// Spring Boot
compile("org.springframework.boot:spring-boot-starter-web")
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
}
The war files get created,but while trying to access the application,it gives the error
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.data.repository.CrudRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
Am I missing anything here ?
If you want to use CrudRepository you need to add a dependency to
spring-boot-starter-data-jpa like
compile("org.springframework.boot:spring-boot-starter-data-jpa")

Resources