Spring boot unresolved reference oauth2 resource server - spring

I asked a question not long ago to know how to validate jwt token using spring boot and copied the dependencies on the sample here but updated them for the latest ones.
This is my build.gradle :
import org.apache.tools.ant.filters.ReplaceTokens
plugins {
id 'org.springframework.boot' version '2.4.5'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'org.jetbrains.kotlin.jvm' version '1.4.32'
id 'org.jetbrains.kotlin.plugin.spring' version '1.4.32'
id "org.jetbrains.kotlin.plugin.jpa" version "1.4.32"
}
apply plugin: 'io.spring.dependency-management'
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'kotlin-jpa'
group = 'com.backend-project'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
def appInsightsVersion = '2.6.2'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-websocket'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
implementation 'com.microsoft.sqlserver:mssql-jdbc:6.2.1.jre8'
implementation 'com.h2database:h2:1.4.199'
implementation 'io.springfox:springfox-swagger2:2.9.2'
implementation 'io.springfox:springfox-swagger-ui:2.9.2'
implementation 'org.jetbrains.kotlin:kotlin-reflect'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
implementation 'org.hibernate:hibernate-core'
implementation 'javax.xml.bind:jaxb-api'
implementation group: 'com.microsoft.azure', name: 'applicationinsights-web', version: appInsightsVersion
implementation group: 'com.microsoft.azure', name: 'applicationinsights-logging-logback', version: appInsightsVersion
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-validation:2.4.5'
implementation 'org.springframework.boot:spring-boot-starter-security:2.4.5'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server:2.4.5'
implementation 'org.springframework.security:spring-security-oauth2-jose:5.3.9.RELEASE'
compile 'org.springframework.security:spring-security-oauth2-core:5.3.9.RELEASE'
compile 'io.jsonwebtoken:jjwt-api:0.11.2'
runtime 'io.jsonwebtoken:jjwt-impl:0.11.2',
'io.jsonwebtoken:jjwt-jackson:0.11.2'
compile 'joda-time:joda-time:2.10.10'
implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.68'
}
compileKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
task copyWebConfig(type: Copy) {
from("$rootDir/src/main/templates") {
include 'web.config'
}
into "$buildDir/libs"
filter(ReplaceTokens, tokens: [VERSION: project.version])
inputs.property("VERSION", project.version)
filter(ReplaceTokens, tokens: [PACKAGE_NAME: project.name])
inputs.property("PACKAGE_NAME", project.name)
}
task copyLogBack(type: Copy) {
from("$rootDir") {
include 'logback-spring.xml'
}
into "$buildDir/libs"
}
assemble.dependsOn(copyWebConfig)
assemble.dependsOn(copyLogBack)
this is my web security implementation :
package com.renaulttrucks.transfertprotocolbackend.security.config
import com.renaulttrucks.transfertprotocolbackend.api.config.Router
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.oauth2.jwt.JwtDecoder
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder
import org.springframework.util.ResourceUtils
import java.io.FileInputStream
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import java.security.interfaces.RSAPublicKey
#EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
#Value("\${security.enabled}")
val securityEnabled : Boolean? = false
#Value("\${jwt.key-path}")
var keyPath: String? = null
var publicKey: RSAPublicKey? = null
override fun configure(http: HttpSecurity) {
if(!securityEnabled!!) {
http.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/**").permitAll()
.and()
.csrf().disable()
.formLogin().disable()
} else {
http
.authorizeRequests()
.antMatchers("/api/companies/**").permitAll()
.antMatchers(Router.API_PATH + "/**").authenticated()
.and()
.httpBasic()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.anonymous()
.and()
.securityContext()
.and()
.headers().disable()
.rememberMe().disable()
.requestCache().disable()
.csrf().disable()
.x509().disable()
.httpBasic().disable()
.formLogin().disable()
.logout().disable()
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt.decoder(jwtDecoder()))
)
}
}
#Bean
fun jwtDecoder(): JwtDecoder? {
return NimbusJwtDecoder.withPublicKey(getPublicKeyFromString()).build()
}
fun getPublicKeyFromString(): RSAPublicKey? {
if (this.publicKey != null) {
return this.publicKey
}
val fin = FileInputStream(ResourceUtils.getFile(keyPath!!))
val f: CertificateFactory = CertificateFactory.getInstance("X.509")
val certificate: X509Certificate = f.generateCertificate(fin) as X509Certificate
publicKey = certificate.getPublicKey() as RSAPublicKey?
return publicKey
}
}
The error happens here :
It gives me the following errors which I don't understand why I'm getting since I'm following the documentation :
Even when trying the kotlin dsl version like here by changing my configure function like bellow :
override fun configure(http: HttpSecurity) {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2ResourceServer {
jwt {
jwtDecoder = jwtDecoder()
}
}
}
}
it gives me the following errors :
The first line's this : : Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public operator fun <T, R> DeepRecursiveFunction<TypeVariable(T), TypeVariable(R)>.invoke(value: TypeVariable(T)): TypeVariable(R) defined in kotlin
Running gradlew dependencyInsight --dependency org.springframework.security:spring-security-config - -configuration runtimeClasspath gives me this :
Welcome to Gradle 7.0!
Here are the highlights of this release:
- File system watching enabled by default
- Support for running with and building Java 16 projects
- Native support for Apple Silicon processors
- Dependency catalog feature preview
For more details see https://docs.gradle.org/7.0/release-notes.html
Starting a Gradle Daemon, 1 busy and 2 incompatible Daemons could not be reused, use --status for details
> Evaluating settings
> Task :dependencyInsight
org.springframework.security:spring-security-config:5.4.6 (selected by rule)
variant "runtime" [
org.gradle.status = release (not requested)
org.gradle.usage = java-runtime
org.gradle.libraryelements = jar
org.gradle.category = library
Requested attributes not found in the selected variant:
org.gradle.dependency.bundling = external
org.gradle.jvm.environment = standard-jvm
org.jetbrains.kotlin.platform.type = jvm
org.gradle.jvm.version = 8
]
org.springframework.security:spring-security-config:5.4.6
+--- org.springframework.boot:spring-boot-starter-oauth2-resource-server:2.4.5
| \--- runtimeClasspath
\--- org.springframework.boot:spring-boot-starter-security:2.4.5
\--- runtimeClasspath
(*) - dependencies omitted (listed previously)
A web-based, searchable dependency report is available by adding the --scan option.
BUILD SUCCESSFUL in 21s
1 actionable task: 1 executed

Using the lambda version solved the issue as user Eleftheria Stein-Kousathana suggested :
oauth2ResourceServer().jwt().decoder(jwtDecoder())

Related

Default profile values are not returned when specific profile selected in Spring Cloud Config

I'm moving from a local application.yml configuration file to a config server managed configuration.
My application.yml file contains 2 (or more) profiles in the same file, in the format:
spring.application.name: config-client
app.myvar1: "Var 1 in default profile"
app.myvar2: "Var 2 in default profile"
---
spring.config.activate.on-profile: docker
app.myvar1: "Var 1 in docker profile"
When I test this configuration file in a NOT config-server environment, I the result reading from the specific profile, and if not found, reading from default. Sample
Correct result when I test without config-server
Profile: docker
MyVar1=Var 1 in docker profile
MyVar2=Var 2 in default profile
For testing I'm using a simple program:
package com.bthinking.configclient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#SpringBootApplication
#RestController
public class ConfigClientApplication {
#Autowired
private Environment environment;
#Value("${app.myvar1:MyVar1 not found}")
String myVar1;
#Value("${app.myvar2:MyVar2 not found}")
String myVar2;
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
#RequestMapping("/")
public String index() {
StringBuffer b = new StringBuffer();
for (String profile : environment.getActiveProfiles()) {
b.append(String.format("Profile: %s</br>", profile));
}
b.append(String.format("MyVar1=%s</br>", myVar1));
b.append(String.format("MyVar2=%s</br>", myVar2));
return b.toString();
}
}
And I start the program with (I use gradle):
gradle :config-client:bootRun --args='--spring.profiles.active=docker'
But, when I migrate to config server, moving the file to a config-repo (I'm using file based repor), I get the invalid result (it's unable to read the variable in the default section). I have also tried with --spring.profiles.active=docker,default with no change
Profile: docker
MyVar1=Var 1 in docker profile
MyVar2=MyVar2 not found
For reference, my config-server has the following configuration:
server.port: 8888
spring.application.name: config-server
spring.cloud.config.server.native.searchLocations: file:${PWD}/config-repo
# spring.cloud.config.server.native.searchLocations: file:/Users/jmalbarran/Projects/BTH/BTH/SPB_SpringBoot/bugs/config/config-repo
logging.level:
root: debug
---
spring.config.activate.on-profile: docker
spring.cloud.config.server.native.searchLocations: file:/config-repo
The main class
package com.bthinking.configserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
#EnableConfigServer
#SpringBootApplication
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
And the build.gradle
plugins {
id 'org.springframework.boot' version '2.4.1'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
group = 'com.b-thinking'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}
ext {
set('springCloudVersion', "2020.0.0")
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-config-server'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
test {
useJUnitPlatform()
}
And I start it with:
gradle :config-server:bootRun --args='--spring.profiles.active=native'
NOTE: As I think this a bug, I have also created an issue in github. Check in Issue
After the #spencergibb (Thanks!) comment, I tried with the version 3.0.1, and it solves the problem.
This is now my build.gradle
plugins {
id 'org.springframework.boot' version '2.4.1'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
group = 'com.b-thinking'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}
ext {
set('springCloudVersion', "2020.0.0")
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-config-server:3.0.1'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
test {
useJUnitPlatform()
}
It's amazing, because the version 3.0.1 is reported solving the opposite bug (the default configuration override the specific), but I imagine that the review solved both.
For references, this were the related issues
Issue#1777 Profile not correct with SpringBoot 2.4.1 + Ilford 2020.0.0 (working with 2.4.1 + Ilford 2020.0.0-RC1)
Issue#1778 multidocument files from config server have the same property name

How to configure spock in spring boot with gradle 6+ and java 11+

I want to use spock in my spring-boot project (using groovy, not java). I have some projects with spock already working in java 8 and lower versions of gradle but I can't find documentation about the newest versions.
This is my OLD build.gradle
buildscript {
ext {
springBootVersion = '2.1.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'groovy'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.test'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter-data-mongodb')
implementation('org.springframework.boot:spring-boot-starter-web')
implementation('org.codehaus.groovy:groovy')
testImplementation('org.springframework.boot:spring-boot-starter-test')
testCompile(
'junit:junit:4.12',
'org.codehaus.groovy:groovy-all:2.4.4',
'org.spockframework:spock-core:1.2-groovy-2.4',
'cglib:cglib:2.2',
'org.spockframework:spock-spring:1.2-groovy-2.4',
)
}
this works and I can create spock tests but when I create a project with java 11 and gradle 6.4, nothing works anymore (the gradle syntax is way different and the spock libraries don't work anymore),
this is my CURRENT (and failing) build.gradle:
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'groovy'
}
group = 'com.test'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.codehaus.groovy:groovy'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'org.postgresql:postgresql'
testImplementation("org.spockframework:spock-core") {
exclude group: "org.codehaus.groovy", module: "groovy-all"
}
testImplementation group: 'org.spockframework', name: 'spock-spring', version: '2.0-M3-groovy-3.0'
testImplementation(enforcedPlatform("org.spockframework:spock-bom:2.0-M1-groovy-2.5"))
}
test {
useJUnitPlatform()
}
With this, nothing works but the gradle build doesn't found the spock-spring libraries.
How can I apply the spock libraries to spring boot with the newest versions of java and gradle?
Think you got into a muddle of Groovy Versions with the dependencies:
I tested with this build:
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'groovy'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
jcenter()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.codehaus.groovy:groovy:3.0.5'
testImplementation('org.spockframework:spock-core:2.0-M3-groovy-3.0')
testImplementation('org.spockframework:spock-spring:2.0-M3-groovy-3.0')
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
And this test ran and passed:
package test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.context.ApplicationContext
import spock.lang.Specification
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = Application)
class ContextSpec extends Specification {
#Autowired
ApplicationContext context
def "context is as expected"() {
expect:
context
context.getBean("echoService")
}
}
(Obviously, I had an echoService in my context)
For completeness, here's the service:
package test
import org.springframework.stereotype.Service
#Service("echoService")
class EchoService {
String echo(String value) {
value?.reverse()
}
}
The controller:
package test
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.RestController
#RestController
class EchoController {
final EchoService echoService
EchoController(EchoService echoService) {
this.echoService = echoService
}
#RequestMapping(
value = "/echo/{message}",
method = RequestMethod.GET,
produces = MediaType.TEXT_PLAIN_VALUE
)
String doEcho(#PathVariable String message) {
return echoService.echo(message)
}
}
And the application class:
package test
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
#SpringBootApplication
class Application {
static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And proof 😉
➜ curl localhost:8080/echo/hello
olleh%

Configuring Camel-Spring for standalone Camel microservice in a multi-module Gradle project

Goal: Adapting Prototype microservice example from Ch7 of Camel in Action by Claus Ibsen into a Gradle multi-module project.
I followed the Spring Guide to 'Creating a Multi Module Project' among other resources.
Project Structure:
+ main-mm-build
|--+ src
|--+ main
|--+ java // Spring Boot microservice (A) in this tree
|--+ build.gradle
|--+ settings.gradle
|--+ contact-manager // standalone-camel-spring microservice (B)
|--+ src
|--+ main
|--+ java // standalone-camel-spring microservice (B) here
|--+ build.gradle
Got as far as:
microservice A (Spring Boot Rest controller) can invoke microservice B (standalone Camel exposing rest() on jetty, without Spring DI).
But what I really want is to use Spring DI (without Spring Boot) in microservice B.
After making changes for camel-spring I get an error.
It's probably mucked up Gradle config, but I could use some help.
main-mm-build/contact-manager$ ../gradlew build
main-mm-build/contact-manager$ java -jar build/libs/contact-manager-1.0.jar
.
.
.
Caused by: org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: rest://get:/contact-manager?consumerComponentName=jetty&consumes=application%2Fjson&outType=...dto.ContactDto%5B%5D&produces=application%2Fjson&routeId=route2 due to: null
at ...impl.engine.AbstractCamelContext.getEndpoint(AbstractCamelContext.java:801)
Caused by: java.lang.NullPointerException
at ...camel.spring.spi.ApplicationContextBeanRepository.lookupByNameAndType(Ap..j:45)
Root project Gradle file:
plugins {
id 'org.springframework.boot' version '2.3.1.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
sourceCompatibility = '11'
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-tomcat'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
allprojects {
group = 'el.cam'
repositories {
jcenter()
}
}
subprojects {
version = '1.0'
}
settings.gradle:
rootProject.name = 'main-mm-build'
include 'contact-manager'
Microservice B (contact-manager) build.gradle:
plugins {
id 'org.springframework.boot'
id 'io.spring.dependency-management'
id 'java'
id 'application'
}
sourceCompatibility = '11'
mainClassName = 'el.cam.contacts.ContactManagerApplication'
task fatJar(type: Jar) {
manifest {
attributes (
'Main-Class': mainClassName
)
}
baseName = 'contact-manager' + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
dependencies {
implementation(platform("org.springframework.boot:spring-boot-dependencies:2.3.1.RELEASE"))
implementation( platform("org.apache.camel:camel-spring-boot-dependencies:3.0.0-RC3") )
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.apache.camel:camel-spring-boot-starter'
implementation 'org.apache.camel:camel-rest-starter'
implementation 'org.apache.camel:camel-jetty-starter'
implementation 'org.apache.camel:camel-jackson-starter'
implementation 'org.apache.camel:camel-swagger-java-starter'// '3.0.0-RC3'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
ContactManagerApplication.java ( I wonder if I'm configuring Spring Camel incorrectly here. All the examples I found were based on Spring boot autoconfiguration, so I just figured it out as I went.)
import el.cam.contacts.configuration.ContactManagerConfiguration;
import org.apache.camel.spring.Main;
public class ContactManagerApplication {
private static final Logger LOG = LoggerFactory.getLogger(ContactManagerApplication.class);
public static void main(String[] args) throws Exception {
Main main = new Main();
main.setApplicationContext(createSpringApplicationContext());
// main.addRoutesBuilder(contactManagerController); // DI using Spring Autowiring
main.run();
}
private static AbstractApplicationContext createSpringApplicationContext() {
AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext();
appContext.register(ContactManagerConfiguration.class);
appContext.refresh();
return appContext;
}
}
Configuration class:
#Configuration
#ComponentScan(basePackages = "el.cam.contacts")
public class ContactManagerConfiguration {
#Autowired
ContactManagerController contactManagerController;
#Bean
public CamelContext camelContext() throws Exception {
SpringCamelContext camelContext = new SpringCamelContext();
camelContext.addRoutes(contactManagerController);
camelContext.setPropertiesComponent(properties());
camelContext.addComponent("rest", rest());
camelContext.addComponent("rest-api", restApi());
camelContext.addComponent("jetty", jetty());
return camelContext;
}
#Bean
public PropertiesComponent properties() throws Exception {
PropertiesComponent properties = new PropertiesComponent();
properties.setLocation("classpath:application.properties");
return properties;
}
#Bean
public RestComponent rest() {
RestComponent rest = new RestComponent();
return rest;
}
#Bean
public RestApiComponent restApi() {
RestApiComponent restApi = new RestApiComponent();
return restApi;
}
#Bean
public JettyHttpComponent jetty() {
JettyHttpComponent jettyHttpComponent = new JettyHttpComponent9();
return jettyHttpComponent;
}
Controller class:
#Component
public class ContactManagerController extends RouteBuilder {
#Autowired
ContactManagerService contactManagerService;
#Override
public void configure() throws Exception {
// before Camel-Spring, was using this to bind serviceBean in camel registry
// getContext().getRegistry().bind("contactManagerService", new ContactManagerService());
// TODO using default. camel property sources not picking up application.properties!
restConfiguration("jetty").port("{{port:8282}}").contextPath("api")
.bindingMode(RestBindingMode.json)
.dataFormatProperty("disableFeatures", "FAIL_ON_EMPTY_BEANS")
.apiContextPath("api-doc")
.enableCORS(true);
// define the rest service
rest("/contact-manager").consumes("application/json").produces("application/json")
.get().outType(ContactDto[].class)
.to("bean:contactManagerService?method=getContacts(${header.contactType})")
;
}
}

Gradle, Kotlin, Multi Module Project: Getting build errors while compiling this project

I am getting the following error on running gradle build command on root folder.
E:\Code\mdh>gradle build
> Task :multidemo:compileKotlin FAILED
e: E:\Code\mdh\multidemo\src\main\kotlin\com\simbalarry\multidemo\SampleController.kt: (3, 23): Unresolved reference: somelib
e: E:\Code\mdh\multidemo\src\main\kotlin\com\simbalarry\multidemo\SampleController.kt: (18, 12): Unresolved reference: Tester
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':multidemo:compileKotlin'.
> Compilation error. See log for more details
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 5s
4 actionable tasks: 1 executed, 3 up-to-date
Below is my project structure and multidemo project is using some functionalities of somelib. Also, I have deliberetly kept somelib as spring boot project as I will be adding more spring boot related functionalities later.
Root Project
|
|---settings.gradle
|---somelib
| |
| |---build.gradle
| |---settings.gradle
| |---src/main/kotlin/somepackage/Tester.kt
| |---src/main/kotlin/somepackage/SomeLibApplication.kt
|
|---multidemo
| |---build.gradle
| |---settings.gradle
| |---src/main/kotlin/somepackage/SampleController.kt
| |---src/main/kotlin/somepackage/MultidemoApplication.kt
Below are the contents of every file
Root/settings.gradle
include ':somelib', ':multidemo'
somelib/build.gradle
plugins {
id 'org.springframework.boot' version '2.1.3.RELEASE'
id 'org.jetbrains.kotlin.jvm' version '1.3.21'
id 'org.jetbrains.kotlin.plugin.spring' version '1.3.21'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.simbalarry'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
implementation 'org.jetbrains.kotlin:kotlin-reflect'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
compileKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
somelib/settings.gradle
pluginManagement {
repositories {
gradlePluginPortal()
}
}
rootProject.name = 'somelib'
somelib/src/main/kotlin/somepackage/Tester.kt
package com.simbalarry.somelib
/*
* Created on : 17-03-2019
* Author : Nayan Kurude
*/
object Tester {
fun getOutputText(): String {
return "Sample Text"
}
}
somelib/src/main/kotlin/somepackage/SomelibApplication.kt
package com.simbalarry.somelib
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
#SpringBootApplication
class SomelibApplication
fun main(args: Array<String>) {
runApplication<SomelibApplication>(*args)
}
multidemo/build.gradle
plugins {
id 'org.springframework.boot' version '2.1.3.RELEASE'
id 'org.jetbrains.kotlin.jvm' version '1.3.21'
id 'org.jetbrains.kotlin.plugin.spring' version '1.3.21'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.simbalarry'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
implementation 'org.jetbrains.kotlin:kotlin-reflect'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
compile project(':somelib')
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
compileKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
multidemo/settings.gradle
pluginManagement {
repositories {
gradlePluginPortal()
}
}
rootProject.name = 'multidemo'
multidemo/src/main/kotlin/somepackage/MultiDemoApplication.kt
package com.simbalarry.multidemo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
#SpringBootApplication
class MultidemoApplication
fun main(args: Array<String>) {
runApplication<MultidemoApplication>(*args)
}
multidemo/src/main/kotlin/somepackage/SampleController.kt
package com.simbalarry.multidemo
import com.simbalarry.somelib.Tester
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
/*
* Created on : 17-03-2019
* Author : Nayan Kurude
*/
#RestController
class SampleController {
#RequestMapping("/hello")
fun hello(): String {
return Tester.getOutputText()
}
}
Could anyone please tell me where am i doing something wrong.
As I said in comments: somelib is supposed to be a library. So it shouldn't apply the spring boot plugin, whose role is to create a Spring Boot application.
Your build.gradle file for somelib should look like this:
plugins {
id 'java-library' // 1
id 'org.springframework.boot' version '2.1.3.RELEASE' apply false // 2
id 'io.spring.dependency-management' version '1.0.6.RELEASE' //3
id 'org.jetbrains.kotlin.jvm' version '1.3.21'
id 'org.jetbrains.kotlin.plugin.spring' version '1.3.21'
}
group = 'com.simbalarry'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencyManagement { // 4
imports {
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
}
}
ext['kotlin.version'] = '1.3.21' // 5
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
implementation 'org.jetbrains.kotlin:kotlin-reflect'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
compileKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '1.8'
}
}
Some explanations (see the comments in the code):
Applies the java library gradle plugin, since that's what you want to create: a library that can be used in the other project
Adds the Spring Boot plugin to the classpath of the build without applying it, in order to be able to use its BOM later. See https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/gradle-plugin/reference/html/#managing-dependencies-using-in-isolation
Applies the spring dependency management plugin to be able to specify dependencies without version, by using the version numbers specified in the spring boot BOM
Configure the dependency management plugin to use the spring boot BOM
Override the kotlin version used in the BOM (1.2.71) by the one you want to use. See https://docs.spring.io/dependency-management-plugin/docs/current-SNAPSHOT/reference/html/#dependency-management-configuration-bom-import-override-property

Dependencies for Spring Integration Amqp in Spring Boot

In order to use Spring Integration Amqp in a Spring Boot application, what are the dependencies I need to include?
Spring Boot version is 2.0.5.
Current dependencies I have are spring-boot-starter-integration and spring-integration-amqp
Error messages are classes like SimpleMessageListenerContainer and AmqpInboundChannelAdapter are not found on the classpath.
UPDATE:
My build.gradle entries --
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.5.RELEASE")
}
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-integration')
compile('org.springframework.boot:spring-boot-starter-amqp')
compile('org.springframework.integration:spring-integration-amqp')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
I had to add the following dependencies to resolve the classes in question (the last in the list did it, using latest spring initalizr, spring-boot 2.0.5)
dependencies {
implementation('org.springframework.boot:spring-boot-starter-amqp')
implementation('org.springframework.boot:spring-boot-starter-integration')
testImplementation('org.springframework.boot:spring-boot-starter-test')
compile 'org.springframework.integration:spring-integration-amqp'
}
To be fair, this answer was already given, just not for gradle.
I am using gradle 4.10.2 on a linux machine, spring-boot initialzr with the options RabbitMQ and Spring-Integration. Here are the changed files:
build.gradle
buildscript {
ext {
springBootVersion = '2.0.5.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter-amqp')
implementation('org.springframework.boot:spring-boot-starter-integration')
testImplementation('org.springframework.boot:spring-boot-starter-test')
compile 'org.springframework.integration:spring-integration-amqp'
}
Implementation of Example 12.2.1 Configuring with Java Configuration from the Spring Integration docs:
package com.example.integrationamqp;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter;
import org.springframework.integration.amqp.inbound.AmqpInboundGateway;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
#SpringBootApplication
public class IntegrationAmqpApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(IntegrationAmqpApplication.class)
.web(WebApplicationType.NONE)
.run(args);
}
#Bean
public MessageChannel amqpInputChannel() {
return new DirectChannel();
}
#Bean
public AmqpInboundChannelAdapter inbound(SimpleMessageListenerContainer listenerContainer,
#Qualifier("amqpInputChannel") MessageChannel channel) {
AmqpInboundChannelAdapter adapter = new AmqpInboundChannelAdapter(listenerContainer);
adapter.setOutputChannel(channel);
return adapter;
}
#Bean
public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container =
new SimpleMessageListenerContainer(connectionFactory);
container.setQueueNames("foo");
container.setConcurrentConsumers(2);
// ...
return container;
}
#Bean
#ServiceActivator(inputChannel = "amqpInputChannel")
public MessageHandler handler() {
return new MessageHandler() {
#Override
public void handleMessage(Message<?> message) throws MessagingException {
System.out.println(message.getPayload());
}
};
}
}
Add this dependency:
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
And are you sure you have this one?:
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-amqp</artifactId>

Resources