diff --git a/buildSrc/settings.gradle b/buildSrc/settings.gradle new file mode 100644 index 00000000000..b5a0fabf664 --- /dev/null +++ b/buildSrc/settings.gradle @@ -0,0 +1,7 @@ +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} diff --git a/buildSrc/src/main/groovy/io.micronaut.build.internal.convention-base.gradle b/buildSrc/src/main/groovy/io.micronaut.build.internal.convention-base.gradle index 3b14a76d3ca..76fde10763c 100644 --- a/buildSrc/src/main/groovy/io.micronaut.build.internal.convention-base.gradle +++ b/buildSrc/src/main/groovy/io.micronaut.build.internal.convention-base.gradle @@ -46,6 +46,15 @@ tasks.withType(Jar).configureEach { preserveFileTimestamps = false } +configurations.all { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + if (details.requested.group == 'org.codehaus.groovy') { + details.useTarget("org.apache.groovy:${details.requested.name}:${details.requested.version}") + details.because "Plugin 'io.micronaut.build.internal.common' isn't Groovy 4 yet and it's pulling in old versions" + } + } +} + dependencies { annotationProcessor libs.bundles.asm annotationProcessor(libs.micronaut.docs.map { diff --git a/buildSrc/src/main/groovy/io.micronaut.build.internal.convention-geb-base.gradle b/buildSrc/src/main/groovy/io.micronaut.build.internal.convention-geb-base.gradle new file mode 100644 index 00000000000..2c0dc4520fa --- /dev/null +++ b/buildSrc/src/main/groovy/io.micronaut.build.internal.convention-geb-base.gradle @@ -0,0 +1,100 @@ +import io.micronaut.build.internal.ext.MicronautCoreExtension +import io.micronaut.build.internal.ext.DefaultMicronautCoreExtension + +plugins { + id "io.micronaut.build.internal.base" + id "groovy" + id "java-library" +} + +micronautBuild { + enableBom = false + enableProcessing = false +} + +group = projectGroupId + +def micronautBuild = (ExtensionAware) project.extensions.getByName("micronautBuild") +def micronautCore = micronautBuild.extensions.create(MicronautCoreExtension, "core", DefaultMicronautCoreExtension, extensions.findByType(VersionCatalogsExtension)) +micronautCore.documented.convention(true) + +if (System.getProperty('geb.env')) { + apply plugin:"com.energizedwork.webdriver-binaries" + + webdriverBinaries { + chromedriver "${chromedriverVersion}" + geckodriver "${geckodriverVersion}" + } +} + +tasks.withType(Test).configureEach { + useJUnitPlatform() + jvmArgs '-Xmx2048m' + systemProperty "micronaut.cloud.platform", "OTHER" + if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_15)) { + jvmArgs "--enable-preview" + } +} + +tasks.named("test") { + systemProperty "geb.env", System.getProperty('geb.env') + systemProperty "webdriver.chrome.driver", System.getProperty('webdriver.chrome.driver') + systemProperty "webdriver.gecko.driver", System.getProperty('webdriver.gecko.driver') +} + +tasks.withType(JavaCompile).configureEach { + options.fork = true + options.compilerArgs.add("-Amicronaut.processing.group=$project.group") + options.compilerArgs.add("-Amicronaut.processing.module=micronaut-$project.name") + options.compilerArgs.add("-Amicronaut.processing.omit.confprop.injectpoints=true") + options.forkOptions.memoryMaximumSize = "2g" +} + +tasks.withType(GroovyCompile).configureEach { + options.fork = true + options.compilerArgs.add("-Amicronaut.processing.group=$project.group") + options.compilerArgs.add("-Amicronaut.processing.module=micronaut-$project.name") + groovyOptions.forkOptions.memoryMaximumSize = "2g" +} + +// This is for reproducible builds +tasks.withType(Jar).configureEach { + reproducibleFileOrder = true + preserveFileTimestamps = false +} + +dependencies { + annotationProcessor libs.bundles.asm + annotationProcessor(libs.micronaut.docs.map { + if (micronautCore.documented.get()) { + it + } else { + null + } + }) { + transitive = false + } + + api libs.managed.slf4j + compileOnly libs.caffeine + compileOnly libs.bundles.asm + + testAnnotationProcessor project(":http-validation") + testAnnotationProcessor libs.bundles.asm + + testImplementation libs.caffeine + testImplementation libs.bundles.asm + + // Geb currently requires Groovy 3, and Spock for Groovy 3 + testImplementation libs.geb.spock + testImplementation libs.spock.for.geb + testImplementation libs.geb.groovy.test + testImplementation libs.selenium.driver.htmlunit + testImplementation libs.selenium.remote.driver + testImplementation libs.selenium.api + testImplementation libs.selenium.support + + testRuntimeOnly libs.htmlunit + testRuntimeOnly libs.selenium.driver.chrome + testRuntimeOnly libs.selenium.driver.firefox +} diff --git a/config/accepted-api-changes.json b/config/accepted-api-changes.json index ea9312644de..b16d69f0b93 100644 --- a/config/accepted-api-changes.json +++ b/config/accepted-api-changes.json @@ -1,5 +1,9 @@ [ - + { + "type": "io.micronaut.http.client.netty.DefaultHttpClient$HttpClientInitializer", + "member": "Constructor io.micronaut.http.client.netty.DefaultHttpClient$HttpClientInitializer(io.micronaut.http.client.netty.DefaultHttpClient,io.netty.handler.ssl.SslContext,java.lang.String,int,boolean,boolean,boolean,java.util.function.Consumer)", + "reason": "4.0.0 Release. All bets are off" + }, { "type": "io.micronaut.ast.groovy.visitor.AbstractGroovyElement", "member": "Class io.micronaut.ast.groovy.visitor.AbstractGroovyElement", diff --git a/gradle/geb.gradle b/gradle/geb.gradle deleted file mode 100644 index f82b46a5b9f..00000000000 --- a/gradle/geb.gradle +++ /dev/null @@ -1,16 +0,0 @@ -dependencies { - testImplementation libs.geb.spock - testImplementation libs.selenium.driver.htmlunit - testRuntimeOnly libs.htmlunit - testImplementation libs.selenium.remote.driver - testImplementation libs.selenium.api - testImplementation libs.selenium.support - testRuntimeOnly libs.selenium.driver.chrome - testRuntimeOnly libs.selenium.driver.firefox -} - -tasks.named("test") { - systemProperty "geb.env", System.getProperty('geb.env') - systemProperty "webdriver.chrome.driver", System.getProperty('webdriver.chrome.driver') - systemProperty "webdriver.gecko.driver", System.getProperty('webdriver.gecko.driver') -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f3fd69eba78..1e734b90d43 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,11 @@ bcpkix = "1.70" blaze = "1.6.7" caffeine = "2.9.3" compile-testing = "0.19" + geb = "3.4.1" +geb-groovy = "3.0.12" +geb-spock = "2.2-groovy-3.0" + hibernate = "5.5.9.Final" hibernate-validator = "6.1.6.Final" htmlSanityCheck = "1.1.6" @@ -48,7 +52,7 @@ managed-gorm-hibernate = "7.3.0" managed-graal-sdk = "22.0.0.2" managed-graal = "22.2.0" managed-graal-svm = "22.0.0.2" -managed-groovy = "3.0.13" +managed-groovy = "4.0.5" managed-h2 = "2.1.210" managed-hystrix = "1.5.18" managed-jakarta-annotation-api = "2.1.1" @@ -134,7 +138,7 @@ managed-reactor = "3.4.23" managed-rxjava1 = "1.3.8" managed-rxjava1-interop = "0.13.7" managed-slf4j = "1.7.36" -managed-spock = "2.0-groovy-3.0" +managed-spock = "2.2-groovy-4.0" managed-spotbugs = "4.7.1" managed-spring = "5.3.23" managed-springboot = "2.7.0" @@ -186,7 +190,7 @@ boms-micronaut-r2dbc = { module = "io.micronaut.r2dbc:micronaut-r2dbc-bom", vers boms-micronaut-flyway = { module = "io.micronaut.flyway:micronaut-flyway-bom", version.ref = "managed-micronaut-flyway" } boms-micronaut-test-resources = { module = "io.micronaut.testresources:micronaut-test-resources-bom", version.ref = "managed-micronaut-test-resources" } -boms-groovy = { module = "org.codehaus.groovy:groovy-bom", version.ref = "managed-groovy" } +boms-groovy = { module = "org.apache.groovy:groovy-bom", version.ref = "managed-groovy" } boms-jackson = { module = "com.fasterxml.jackson:jackson-bom", version.ref = "managed-jackson" } boms-junit5 = { module = "org.junit:junit-bom", version.ref = "managed-junit5" } boms-kotlin = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "managed-kotlin" } @@ -227,10 +231,10 @@ managed-gorm-hibernate = { module = "org.grails:grails-datastore-gorm-hibernate5 managed-graal = { module = "org.graalvm.nativeimage:svm", version.ref = "managed-graal-svm" } managed-graal-sdk = { module = "org.graalvm.sdk:graal-sdk", version.ref = "managed-graal-sdk" } -managed-groovy = { module = "org.codehaus.groovy:groovy", version.ref = "managed-groovy" } -managed-groovy-json = { module = "org.codehaus.groovy:groovy-json", version.ref = "managed-groovy" } -managed-groovy-sql = { module = "org.codehaus.groovy:groovy-sql", version.ref = "managed-groovy" } -managed-groovy-templates = { module = "org.codehaus.groovy:groovy-templates", version.ref = "managed-groovy" } +managed-groovy = { module = "org.apache.groovy:groovy", version.ref = "managed-groovy" } +managed-groovy-json = { module = "org.apache.groovy:groovy-json", version.ref = "managed-groovy" } +managed-groovy-sql = { module = "org.apache.groovy:groovy-sql", version.ref = "managed-groovy" } +managed-groovy-templates = { module = "org.apache.groovy:groovy-templates", version.ref = "managed-groovy" } managed-h2 = { module = "com.h2database:h2", version.ref = "managed-h2" } @@ -365,8 +369,10 @@ caffeine = { module = "com.github.ben-manes.caffeine:caffeine", version.ref = "c compile-testing = { module = "com.google.testing.compile:compile-testing", version.ref = "compile-testing" } geb-spock = { module = "org.gebish:geb-spock", version.ref = "geb" } +spock-for-geb = { module = "org.spockframework:spock-core", version.ref = "geb-spock" } +geb-groovy-test = { module = "org.codehaus.groovy:groovy-test", version.ref = "geb-groovy" } -groovy-test-junit5 = { module = "org.codehaus.groovy:groovy-test-junit5", version.ref = "managed-groovy" } +groovy-test-junit5 = { module = "org.apache.groovy:groovy-test-junit5", version.ref = "managed-groovy" } hibernate = { module = "org.hibernate:hibernate-core", version.ref = "hibernate" } hibernate-validator = { module = "org.hibernate:hibernate-validator", version.ref = "hibernate-validator" } diff --git a/gradle/webdriverbinaries.gradle b/gradle/webdriverbinaries.gradle deleted file mode 100644 index 454f66613e4..00000000000 --- a/gradle/webdriverbinaries.gradle +++ /dev/null @@ -1,9 +0,0 @@ -if (System.getProperty('geb.env')) { - apply plugin:"com.energizedwork.webdriver-binaries" - - webdriverBinaries { - chromedriver "${chromedriverVersion}" - geckodriver "${geckodriverVersion}" - } -} - diff --git a/http-client-core/src/test/groovy/io/micronaut/http/client/SocketAddressSpec.groovy b/http-client-core/src/test/groovy/io/micronaut/http/client/SocketAddressSpec.groovy index 082eee79395..8efc2e56cce 100644 --- a/http-client-core/src/test/groovy/io/micronaut/http/client/SocketAddressSpec.groovy +++ b/http-client-core/src/test/groovy/io/micronaut/http/client/SocketAddressSpec.groovy @@ -13,7 +13,7 @@ class SocketAddressSpec extends Specification { ConversionService converter = ctx.getBean(ConversionService) when: - Optional address = converter.convert("1.2.3.4:8080", SocketAddress.class) + Optional address = converter.convert("1.2.3.4:8080", SocketAddress) then: address.isPresent() @@ -22,7 +22,7 @@ class SocketAddressSpec extends Specification { ((InetSocketAddress) address.get()).getPort() == 8080 when: - address = converter.convert("https://foo.bar:8081", SocketAddress.class) + address = converter.convert("https://foo.bar:8081", SocketAddress) then: address.isPresent() @@ -31,7 +31,7 @@ class SocketAddressSpec extends Specification { ((InetSocketAddress) address.get()).getPort() == 8081 when: - ConversionContext conversionContext = ArgumentConversionContext.of(SocketAddress.class) + ConversionContext conversionContext = ConversionContext.of(SocketAddress) address = converter.convert("abc:456456456456", conversionContext) then: diff --git a/http-server-netty/build.gradle b/http-server-netty/build.gradle index bc871ce3e97..a568bdf19f5 100644 --- a/http-server-netty/build.gradle +++ b/http-server-netty/build.gradle @@ -45,6 +45,7 @@ dependencies { testImplementation(libs.managed.micronaut.xml) { exclude module:'micronaut-inject' exclude module:'micronaut-http' + exclude module:'micronaut-bom' } testImplementation libs.managed.jackson.databind diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/HttpResponseSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/HttpResponseSpec.groovy index df3fe92a1cc..2c2ea5d784e 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/HttpResponseSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/HttpResponseSpec.groovy @@ -162,7 +162,7 @@ class HttpResponseSpec extends AbstractMicronautSpec { void "test server header"() { given: - EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['micronaut.server.serverHeader': 'Foo!', (SPEC_NAME_PROPERTY):getClass().simpleName]) + EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['micronaut.server.server-header': 'Foo!', (SPEC_NAME_PROPERTY):getClass().simpleName]) def ctx = server.getApplicationContext() HttpClient client = ctx.createBean(HttpClient, server.getURL()) @@ -216,7 +216,7 @@ class HttpResponseSpec extends AbstractMicronautSpec { void "test date header turned off"() { given: - EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['micronaut.server.dateHeader': false, (SPEC_NAME_PROPERTY):getClass().simpleName]) + EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['micronaut.server.date-header': false, (SPEC_NAME_PROPERTY):getClass().simpleName]) ApplicationContext ctx = server.getApplicationContext() HttpClient client = ctx.createBean(HttpClient, server.getURL()) @@ -234,9 +234,9 @@ class HttpResponseSpec extends AbstractMicronautSpec { void "test keep alive connection header is not set by default for > 499 response"() { when: - EmbeddedServer server = applicationContext.run(EmbeddedServer, [(SPEC_NAME_PROPERTY):getClass().simpleName]) + EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['micronaut.server.date-header': false, (SPEC_NAME_PROPERTY):getClass().simpleName]) ApplicationContext ctx = server.getApplicationContext() - HttpClient client = applicationContext.createBean(HttpClient, embeddedServer.getURL()) + HttpClient client = ctx.createBean(HttpClient, server.getURL()) Flux.from(client.exchange( HttpRequest.GET('/test-header/fail') @@ -256,14 +256,16 @@ class HttpResponseSpec extends AbstractMicronautSpec { void "test connection header is defaulted to keep-alive when configured to true for > 499 response"() { when: DefaultHttpClientConfiguration config = new DefaultHttpClientConfiguration() + // The client will explicitly request "Connection: close" unless using a connection pool, so set it up config.connectionPoolConfiguration.enabled = true - EmbeddedServer server = applicationContext.run(EmbeddedServer, [ + + EmbeddedServer server = ApplicationContext.run(EmbeddedServer, [ (SPEC_NAME_PROPERTY):getClass().simpleName, 'micronaut.server.netty.keepAliveOnServerError':true ]) def ctx = server.getApplicationContext() - HttpClient client = applicationContext.createBean(HttpClient, embeddedServer.getURL(), config) + HttpClient client = ctx.createBean(HttpClient, embeddedServer.getURL(), config) Flux.from(client.exchange( HttpRequest.GET('/test-header/fail') @@ -301,6 +303,6 @@ class HttpResponseSpec extends AbstractMicronautSpec { @Override Map getConfiguration() { - super.getConfiguration() << ['micronaut.server.dateHeader': false] + super.getConfiguration() << ['micronaut.server.date-header': false] } } diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/jackson/JsonFactorySetupSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/jackson/JsonFactorySetupSpec.groovy index e70567c60c7..ade665a8be6 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/jackson/JsonFactorySetupSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/jackson/JsonFactorySetupSpec.groovy @@ -16,15 +16,11 @@ package io.micronaut.http.server.netty.jackson import com.fasterxml.jackson.core.JsonFactory -import com.fasterxml.jackson.core.util.BufferRecycler import com.fasterxml.jackson.databind.ObjectMapper import io.micronaut.context.ApplicationContext import io.micronaut.context.DefaultApplicationContext import io.micronaut.context.env.MapPropertySource -import io.micronaut.docs.context.annotation.primary.ColorPicker -import io.micronaut.http.HttpRequest -import io.micronaut.http.HttpResponse -import io.micronaut.http.HttpStatus +import io.micronaut.context.env.PropertySource import spock.lang.Specification /** @@ -34,7 +30,6 @@ import spock.lang.Specification class JsonFactorySetupSpec extends Specification { void "verify default jackson setup with JsonFactory bean"() { - given: ApplicationContext applicationContext = new DefaultApplicationContext("test").start() @@ -49,7 +44,7 @@ class JsonFactorySetupSpec extends Specification { void "verify JsonFactory properties are injected into the bean"() { given: ApplicationContext applicationContext = new DefaultApplicationContext("test") - applicationContext.environment.addPropertySource(MapPropertySource.of( + applicationContext.environment.addPropertySource((MapPropertySource) PropertySource.of( 'jackson.factory.use-thread-local-for-buffer-recycling': false )) applicationContext.start() diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/jackson/JsonViewSetupSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/jackson/JsonViewSetupSpec.groovy index bf1c5425324..d25315fb12f 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/jackson/JsonViewSetupSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/jackson/JsonViewSetupSpec.groovy @@ -19,6 +19,7 @@ package io.micronaut.http.server.netty.jackson import io.micronaut.context.ApplicationContext import io.micronaut.context.DefaultApplicationContext import io.micronaut.context.env.MapPropertySource +import io.micronaut.context.env.PropertySource import io.micronaut.jackson.JacksonConfiguration import spock.lang.Specification @@ -43,7 +44,7 @@ class JsonViewSetupSpec extends Specification { given: ApplicationContext applicationContext = new DefaultApplicationContext("test") - applicationContext.environment.addPropertySource(MapPropertySource.of( + applicationContext.environment.addPropertySource((MapPropertySource) PropertySource.of( 'jackson.json-view.enabled': true )) applicationContext.start() diff --git a/inject-groovy-test/build.gradle b/inject-groovy-test/build.gradle index 34e0b706f7e..29e331e3e82 100644 --- a/inject-groovy-test/build.gradle +++ b/inject-groovy-test/build.gradle @@ -11,6 +11,7 @@ dependencies { exclude module:'groovy-all' } api project(":context") + api libs.jetbrains.annotations } tasks.named("sourcesJar") { diff --git a/inject-groovy/src/main/groovy/io/micronaut/ast/groovy/visitor/GroovyClassElement.java b/inject-groovy/src/main/groovy/io/micronaut/ast/groovy/visitor/GroovyClassElement.java index efec5f1f4d7..b76bd1abdde 100644 --- a/inject-groovy/src/main/groovy/io/micronaut/ast/groovy/visitor/GroovyClassElement.java +++ b/inject-groovy/src/main/groovy/io/micronaut/ast/groovy/visitor/GroovyClassElement.java @@ -906,7 +906,7 @@ public Optional getReadMethod() { private String getGetterName(String propertyName, ClassElement type) { return NameUtils.getterNameFor( propertyName, - type.equals(PrimitiveElement.BOOLEAN) || type.getName().equals(Boolean.class.getName()) + type.equals(PrimitiveElement.BOOLEAN) ); } }; diff --git a/inject-groovy/src/test/groovy/io/micronaut/inject/requires/RequiresBeanPropertiesSpec.groovy b/inject-groovy/src/test/groovy/io/micronaut/inject/requires/RequiresBeanPropertiesSpec.groovy index 0cd639f96af..f4ba769afe2 100644 --- a/inject-groovy/src/test/groovy/io/micronaut/inject/requires/RequiresBeanPropertiesSpec.groovy +++ b/inject-groovy/src/test/groovy/io/micronaut/inject/requires/RequiresBeanPropertiesSpec.groovy @@ -113,6 +113,39 @@ class Config Boolean boolProperty } +@Singleton +@Requires(bean = Config.class, beanProperty = "boolProperty", notEquals = "true") +class DependantBean +{ +} +''') + def type = context.classLoader.loadClass('test.DependantBean') + + when: + context.environment.addPropertySource(PropertySource.of("test", ['test.bool-property': "true"])) + context.getBean(type) + + then: + thrown(NoSuchBeanException.class) + + cleanup: + context.close() + } + + void "test requires not equals property value with primitive value set"() { + given: + ApplicationContext context = buildContext(''' +package test +import io.micronaut.context.annotation.* +import io.micronaut.core.annotation.* +import jakarta.inject.Singleton + +@ConfigurationProperties("test") +class Config +{ + boolean boolProperty +} + @Singleton @Requires(bean = Config.class, beanProperty = "boolProperty", notEquals = "true") class DependantBean @@ -143,11 +176,11 @@ import jakarta.inject.Singleton @ConfigurationProperties("config.properties") class Config { private String property - + public String getProperty() { return property; } - + public void setProperty(String property) { this.property = property; } @@ -561,7 +594,7 @@ class Config { Integer intProperty String stringProperty - + @ConfigurationProperties("inner") static class InnerConfig { String innerProperty = "default value" @@ -615,7 +648,7 @@ interface Configuration extends Toggleable {} class ConfigurationImpl implements Configuration { boolean enabled = false; - + @Override boolean isEnabled() { return enabled; diff --git a/inject-java-test/build.gradle b/inject-java-test/build.gradle index 74d6da36bd9..63a7dbdad7a 100644 --- a/inject-java-test/build.gradle +++ b/inject-java-test/build.gradle @@ -17,6 +17,7 @@ dependencies { if (!JavaVersion.current().isJava9Compatible()) { api files(org.gradle.internal.jvm.Jvm.current().toolsJar) } + api libs.jetbrains.annotations testAnnotationProcessor project(":inject-java") testCompileOnly project(":inject-groovy") diff --git a/inject-java/src/test/groovy/io/micronaut/inject/beans/AbstractBeanSpec.groovy b/inject-java/src/test/groovy/io/micronaut/inject/beans/AbstractBeanSpec.groovy index c2ea3c6793d..b2d80c2ebba 100644 --- a/inject-java/src/test/groovy/io/micronaut/inject/beans/AbstractBeanSpec.groovy +++ b/inject-java/src/test/groovy/io/micronaut/inject/beans/AbstractBeanSpec.groovy @@ -17,7 +17,7 @@ package io.micronaut.inject.beans import io.micronaut.aop.Intercepted import io.micronaut.context.ApplicationContext -import io.micronaut.context.DefaultBeanContext +import io.micronaut.context.BeanContext import io.micronaut.annotation.processing.test.AbstractTypeElementSpec import io.micronaut.inject.BeanDefinition @@ -37,7 +37,7 @@ import jakarta.inject.Inject; import java.util.List; class Test { - + @Inject List list; } @@ -84,7 +84,7 @@ abstract class AbstractBean { void "test getBeansOfType filters proxy targets"() { when: - def ctx = DefaultBeanContext.run() + def ctx = BeanContext.run() def targetBean = ctx.getProxyTargetBean(InterceptedBean, null) def bean = ctx.getBean(InterceptedBean) @@ -102,7 +102,7 @@ abstract class AbstractBean { void "test getBeansOfType filters proxy targets with context scoped beans"() { when: - def ctx = DefaultBeanContext.run() + def ctx = BeanContext.run() def targetBean = ctx.getProxyTargetBean(ContextScopedInterceptedBean, null) def bean = ctx.getBean(ContextScopedInterceptedBean) @@ -120,7 +120,7 @@ abstract class AbstractBean { void "test getBeansOfType filters proxy targets with parallel beans"() { when: - def ctx = DefaultBeanContext.run() + def ctx = BeanContext.run() Thread.sleep(100) def targetBean = ctx.getProxyTargetBean(ParallelBean, null) def bean = ctx.getBean(ParallelBean) diff --git a/inject-java/src/test/groovy/io/micronaut/inject/beans/inheritance/InheritanceSingletonSpec.groovy b/inject-java/src/test/groovy/io/micronaut/inject/beans/inheritance/InheritanceSingletonSpec.groovy index 77b287e2917..7939a3a61a9 100644 --- a/inject-java/src/test/groovy/io/micronaut/inject/beans/inheritance/InheritanceSingletonSpec.groovy +++ b/inject-java/src/test/groovy/io/micronaut/inject/beans/inheritance/InheritanceSingletonSpec.groovy @@ -1,13 +1,13 @@ package io.micronaut.inject.beans.inheritance -import io.micronaut.context.DefaultBeanContext +import io.micronaut.context.BeanContext import io.micronaut.inject.qualifiers.Qualifiers import spock.lang.Specification class InheritanceSingletonSpec extends Specification { void "test getBeansOfType returns the same instance"() { - def ctx = DefaultBeanContext.run() + def ctx = BeanContext.run() def bankService = ctx.getBean(BankService) when: diff --git a/inject-kotlin-test/build.gradle b/inject-kotlin-test/build.gradle index 537b5280c58..842fefc0611 100644 --- a/inject-kotlin-test/build.gradle +++ b/inject-kotlin-test/build.gradle @@ -43,3 +43,20 @@ tasks.named("compileGroovy") { dependsOn tasks.getByPath('compileKotlin') classpath += files(compileKotlin.destinationDirectory) } + +tasks.named("test", Test) { + if(JavaVersion.current().majorVersion.toInteger() >= 17) { + jvmArgs( + '--add-opens', 'jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED', + '--add-opens', 'jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED', + '--add-opens', 'jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED', + '--add-opens', 'jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED', + '--add-opens', 'jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED', + '--add-opens', 'jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED', + '--add-opens', 'jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED', + '--add-opens', 'jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED', + '--add-opens', 'jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED', + '--add-opens', 'jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED' + ) + } +} diff --git a/inject-kotlin-test/src/main/kotlin/io/micronaut/annotation/processing/test/KotlinCompileHelper.kt b/inject-kotlin-test/src/main/kotlin/io/micronaut/annotation/processing/test/KotlinCompileHelper.kt index 36bdaa7825e..2735410a962 100644 --- a/inject-kotlin-test/src/main/kotlin/io/micronaut/annotation/processing/test/KotlinCompileHelper.kt +++ b/inject-kotlin-test/src/main/kotlin/io/micronaut/annotation/processing/test/KotlinCompileHelper.kt @@ -120,7 +120,8 @@ object KotlinCompileHelper { message: String, location: CompilerMessageSourceLocation? ) { - if (severity == CompilerMessageSeverity.ERROR) { + // With Java 17 and Groovy 4.x this breaks inject-kotlin-test:KotlinCompilerTest as it throws an AssertionError for the Note: message + if (severity == CompilerMessageSeverity.ERROR && !message.startsWith("Note:")) { throw AssertionError("Error reported in processing: $message") } } diff --git a/inject-kotlin-test/src/test/groovy/io/micronaut/annotation/processing/test/KotlinCompilerTest.groovy b/inject-kotlin-test/src/test/groovy/io/micronaut/annotation/processing/test/KotlinCompilerTest.groovy index b5aa8eec46a..ed249f9cc34 100644 --- a/inject-kotlin-test/src/test/groovy/io/micronaut/annotation/processing/test/KotlinCompilerTest.groovy +++ b/inject-kotlin-test/src/test/groovy/io/micronaut/annotation/processing/test/KotlinCompilerTest.groovy @@ -2,14 +2,11 @@ package io.micronaut.annotation.processing.test import io.micronaut.core.beans.BeanIntrospection import io.micronaut.core.version.SemanticVersion +import spock.lang.Ignore +import spock.lang.IgnoreIf import spock.lang.Requires import spock.util.environment.Jvm -// fails due to https://issues.apache.org/jira/browse/GROOVY-10145 -@Requires({ - SemanticVersion.isAtLeastMajorMinor(GroovySystem.version, 4, 0) || - !Jvm.current.isJava16Compatible() -}) class KotlinCompilerTest extends AbstractKotlinCompilerSpec { void "simple class"() { given: @@ -53,7 +50,7 @@ class Foo { @Singleton class Bar { - + } ''') def bean = getBean(context, "example.Foo") diff --git a/inject/src/test/groovy/io/micronaut/inject/util/VisitorContextUtilsSpec.groovy b/inject/src/test/groovy/io/micronaut/inject/util/VisitorContextUtilsSpec.groovy index 0dcd9e31419..7adc5b4a204 100644 --- a/inject/src/test/groovy/io/micronaut/inject/util/VisitorContextUtilsSpec.groovy +++ b/inject/src/test/groovy/io/micronaut/inject/util/VisitorContextUtilsSpec.groovy @@ -8,6 +8,7 @@ import javax.annotation.processing.ProcessingEnvironment @Stepwise class VisitorContextUtilsSpec extends Specification { + public static final String INVALID_CUSTOM_PROP_1 = "invalid.custom.prop" public static final String VALID_CUSTOM_PROP_1 = "micronaut.custom.prop" public static final String VALID_CUSTOM_PROP_2 = "micronaut.another.custom.prop" @@ -52,9 +53,9 @@ class VisitorContextUtilsSpec extends Specification { with(options) { size() == 2 - containsKey(VALID_CUSTOM_PROP_1) - containsKey(VALID_CUSTOM_PROP_2) - !containsKey(INVALID_CUSTOM_PROP_1) + containsKey(VisitorContextUtilsSpec.VALID_CUSTOM_PROP_1) + containsKey(VisitorContextUtilsSpec.VALID_CUSTOM_PROP_2) + !containsKey(VisitorContextUtilsSpec.INVALID_CUSTOM_PROP_1) } } diff --git a/jackson-databind/src/test/groovy/io/micronaut/jackson/JacksonSetupSpec.groovy b/jackson-databind/src/test/groovy/io/micronaut/jackson/JacksonSetupSpec.groovy index 7ff2a480e05..c591717d28e 100644 --- a/jackson-databind/src/test/groovy/io/micronaut/jackson/JacksonSetupSpec.groovy +++ b/jackson-databind/src/test/groovy/io/micronaut/jackson/JacksonSetupSpec.groovy @@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.SerializationFeature import io.micronaut.context.ApplicationContext import io.micronaut.context.DefaultApplicationContext import io.micronaut.context.env.MapPropertySource +import io.micronaut.context.env.PropertySource import spock.lang.Specification import spock.lang.Unroll @@ -61,7 +62,7 @@ class JacksonSetupSpec extends Specification { given: ApplicationContext applicationContext = new DefaultApplicationContext("test") - applicationContext.environment.addPropertySource(MapPropertySource.of( + applicationContext.environment.addPropertySource((MapPropertySource) PropertySource.of( 'jackson.dateFormat': 'yyMMdd', 'jackson.serialization.indentOutput': true, 'jackson.json-view.enabled': true @@ -83,7 +84,7 @@ class JacksonSetupSpec extends Specification { void "verify that the defaultTyping configuration option is correctly converted and set on the object mapper"() { given: ApplicationContext applicationContext = new DefaultApplicationContext("test") - applicationContext.environment.addPropertySource(MapPropertySource.of( + applicationContext.environment.addPropertySource((MapPropertySource) PropertySource.of( 'jackson.dateFormat': 'yyMMdd', 'jackson.defaultTyping': 'NON_FINAL' )) @@ -103,7 +104,7 @@ class JacksonSetupSpec extends Specification { @Unroll void 'Configuring #configuredJackonPropertyNamingStrategy sets PropertyNamingStrategy on the Context ObjectMapper.'() { when: - ApplicationContext applicationContext = ApplicationContext.run(MapPropertySource.of( + ApplicationContext applicationContext = ApplicationContext.run((MapPropertySource) PropertySource.of( 'jackson.property-naming-strategy': configuredJackonPropertyNamingStrategy.toString() )) @@ -137,7 +138,7 @@ class JacksonSetupSpec extends Specification { void "verify trim strings with custom property enabled"() { given: ApplicationContext applicationContext = new DefaultApplicationContext("test") - applicationContext.environment.addPropertySource(MapPropertySource.of( + applicationContext.environment.addPropertySource((MapPropertySource) PropertySource.of( 'jackson.trim-strings': true )) applicationContext.start() diff --git a/jackson-databind/src/test/groovy/io/micronaut/jackson/bind/CharSequencePropertyNamingStrategyConverterSpec.groovy b/jackson-databind/src/test/groovy/io/micronaut/jackson/bind/CharSequencePropertyNamingStrategyConverterSpec.groovy index fbacffb6fd7..342be9255b3 100644 --- a/jackson-databind/src/test/groovy/io/micronaut/jackson/bind/CharSequencePropertyNamingStrategyConverterSpec.groovy +++ b/jackson-databind/src/test/groovy/io/micronaut/jackson/bind/CharSequencePropertyNamingStrategyConverterSpec.groovy @@ -18,7 +18,6 @@ package io.micronaut.jackson.bind import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.PropertyNamingStrategy import io.micronaut.context.ApplicationContext -import io.micronaut.core.convert.ArgumentConversionContext import io.micronaut.core.convert.ConversionContext import io.micronaut.core.convert.ConversionError import io.micronaut.core.convert.ConversionService @@ -61,7 +60,7 @@ class CharSequencePropertyNamingStrategyConverterSpec extends Specification { def converter = ctx.getBean(ConversionService) when: - ConversionContext conversionContext = ArgumentConversionContext.of(CharSequence) + ConversionContext conversionContext = ConversionContext.of(CharSequence) converter.convert(invalidString, PropertyNamingStrategy, conversionContext) ConversionError conversionError = conversionContext.last() diff --git a/settings.gradle b/settings.gradle index 2a4ada517da..277e478b387 100644 --- a/settings.gradle +++ b/settings.gradle @@ -58,6 +58,7 @@ include "websocket" // test suites include "test-suite" +include "test-suite-geb" include "test-suite-helper" include "test-suite-javax-inject" include "test-suite-jakarta-inject-bean-import" diff --git a/src/main/docs/guide/appendix/breaks.adoc b/src/main/docs/guide/appendix/breaks.adoc index e6e3e7490fa..c2b8b0e978b 100644 --- a/src/main/docs/guide/appendix/breaks.adoc +++ b/src/main/docs/guide/appendix/breaks.adoc @@ -8,6 +8,12 @@ This section documents breaking changes between Micronaut versions https://github.com/ben-manes/caffeine[Caffeine] is no longer shaded into the `io.micronaut.caffeine` package. If you depend on this library you should directly depend on the latest version of Caffeine. +==== Update to Groovy 4 + +Micronaut now uses Groovy 4. +This means that Groovy 4 is now the minimum version required to run Groovy Micronaut applications. +There have been several core differences in Groovy parsing and behavior for version 4 which can be found in the breaking changes section of the https://groovy-lang.org/releasenotes/groovy-4.0.html[4.0.0 release notes]. + ==== SnakeYAML no longer a direct dependency SnakeYAML is no longer a direct dependency, if you need YAML configuration you should add SnakeYAML to your classpath explicitly diff --git a/test-suite-geb/build.gradle b/test-suite-geb/build.gradle new file mode 100644 index 00000000000..2ae34854e5f --- /dev/null +++ b/test-suite-geb/build.gradle @@ -0,0 +1,21 @@ +plugins { + id "io.micronaut.build.internal.convention-geb-base" +} + +micronautBuild { + core { + usesMicronautTestJunit() + usesMicronautTestSpock() + } +} + +dependencies { + testImplementation(project(":inject-groovy")) { + exclude module: 'groovy' + } + + testImplementation project(':http') + testImplementation project(':http-server-netty') + + testRuntimeOnly "ch.qos.logback:logback-classic:1.2.3" +} diff --git a/test-suite-geb/src/test/groovy/io/micronaut/upload/browser/CreatePage.groovy b/test-suite-geb/src/test/groovy/io/micronaut/upload/browser/CreatePage.groovy new file mode 100644 index 00000000000..b68bcf4606d --- /dev/null +++ b/test-suite-geb/src/test/groovy/io/micronaut/upload/browser/CreatePage.groovy @@ -0,0 +1,18 @@ +package io.micronaut.upload.browser + +import geb.Page + +class CreatePage extends Page { + + static url = '/image/create' + + static at = { title == 'Create Image' } + + static content = { + uploadButton { $('input', type: 'submit', value: 'Upload') } + } + + void upload() { + uploadButton.click() + } +} diff --git a/test-suite-geb/src/test/groovy/io/micronaut/upload/browser/FileEmptyPage.groovy b/test-suite-geb/src/test/groovy/io/micronaut/upload/browser/FileEmptyPage.groovy new file mode 100644 index 00000000000..7495add2d5a --- /dev/null +++ b/test-suite-geb/src/test/groovy/io/micronaut/upload/browser/FileEmptyPage.groovy @@ -0,0 +1,10 @@ +package io.micronaut.upload.browser + +import geb.Page + +class FileEmptyPage extends Page { + + static url = '/image/save' + + static at = { title == 'File is Empty' } +} diff --git a/test-suite/src/test/groovy/io/micronaut/upload/browser/UploadBrowserSpec.groovy b/test-suite-geb/src/test/groovy/io/micronaut/upload/browser/UploadBrowserSpec.groovy similarity index 61% rename from test-suite/src/test/groovy/io/micronaut/upload/browser/UploadBrowserSpec.groovy rename to test-suite-geb/src/test/groovy/io/micronaut/upload/browser/UploadBrowserSpec.groovy index d9baf8e4630..23163f7a040 100644 --- a/test-suite/src/test/groovy/io/micronaut/upload/browser/UploadBrowserSpec.groovy +++ b/test-suite-geb/src/test/groovy/io/micronaut/upload/browser/UploadBrowserSpec.groovy @@ -1,18 +1,3 @@ -/* - * Copyright 2017-2019 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package io.micronaut.upload.browser import geb.spock.GebSpec diff --git a/test-suite/src/test/groovy/io/micronaut/upload/browser/UploadImageController.groovy b/test-suite-geb/src/test/groovy/io/micronaut/upload/browser/UploadImageController.groovy similarity index 65% rename from test-suite/src/test/groovy/io/micronaut/upload/browser/UploadImageController.groovy rename to test-suite-geb/src/test/groovy/io/micronaut/upload/browser/UploadImageController.groovy index 4692f9851ac..04c9489b6ec 100644 --- a/test-suite/src/test/groovy/io/micronaut/upload/browser/UploadImageController.groovy +++ b/test-suite-geb/src/test/groovy/io/micronaut/upload/browser/UploadImageController.groovy @@ -1,18 +1,3 @@ -/* - * Copyright 2017-2020 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package io.micronaut.upload.browser import io.micronaut.context.annotation.Requires @@ -42,7 +27,4 @@ class UploadImageController { String title = file.getSize() == 0 ? 'File is Empty' : 'File Saved' "${title}" } - - - } diff --git a/test-suite/src/test/resources/GebConfig.groovy b/test-suite-geb/src/test/resources/GebConfig.groovy similarity index 100% rename from test-suite/src/test/resources/GebConfig.groovy rename to test-suite-geb/src/test/resources/GebConfig.groovy diff --git a/test-suite-geb/src/test/resources/logback.xml b/test-suite-geb/src/test/resources/logback.xml new file mode 100644 index 00000000000..44b79c40d49 --- /dev/null +++ b/test-suite-geb/src/test/resources/logback.xml @@ -0,0 +1,14 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + diff --git a/test-suite-groovy/build.gradle b/test-suite-groovy/build.gradle index 9aab800b056..5b8cf4f1a9f 100644 --- a/test-suite-groovy/build.gradle +++ b/test-suite-groovy/build.gradle @@ -28,15 +28,9 @@ dependencies { testImplementation project(":function-web") testRuntimeOnly(platform(libs.boms.micronaut.aws)) testRuntimeOnly libs.aws.java.sdk.lambda + testRuntimeOnly libs.bcpkix testImplementation libs.managed.reactor } -//tasks.withType(Test).configureEach { -// testLogging { -// showStandardStreams = true -// exceptionFormat = 'full' -// } -//} - //compileTestGroovy.groovyOptions.forkOptions.jvmArgs = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005'] diff --git a/test-suite-groovy/src/test/groovy/io/micronaut/docs/http/server/secondary/SecondaryServerTest.groovy b/test-suite-groovy/src/test/groovy/io/micronaut/docs/http/server/secondary/SecondaryServerTest.groovy index fe04d6d16ea..3c75829bc89 100644 --- a/test-suite-groovy/src/test/groovy/io/micronaut/docs/http/server/secondary/SecondaryServerTest.groovy +++ b/test-suite-groovy/src/test/groovy/io/micronaut/docs/http/server/secondary/SecondaryServerTest.groovy @@ -19,11 +19,6 @@ import spock.util.environment.Jvm @MicronautTest @Property(name = "secondary.enabled", value = StringUtils.TRUE) @Property(name = "micronaut.http.client.ssl.insecure-trust-all-certificates", value = StringUtils.TRUE) -// fails due to https://issues.apache.org/jira/browse/GROOVY-10145 -@Requires({ - SemanticVersion.isAtLeastMajorMinor(GroovySystem.version, 4, 0) || - !Jvm.current.isJava16Compatible() -}) class SecondaryServerTest extends Specification { // tag::inject[] @Client(path = "/", id = SecondaryNettyServer.SERVER_ID) diff --git a/test-suite/build.gradle b/test-suite/build.gradle index e3375e3fb0f..8a7f190001b 100644 --- a/test-suite/build.gradle +++ b/test-suite/build.gradle @@ -22,9 +22,6 @@ micronautBuild { } } -apply from: "${rootProject.projectDir}/gradle/geb.gradle" -apply from: "${rootProject.projectDir}/gradle/webdriverbinaries.gradle" - dependencies { annotationProcessor project(":inject-java") api project(":inject") @@ -56,6 +53,7 @@ dependencies { exclude module: 'micronaut-runtime' } testImplementation libs.managed.groovy.json + testImplementation libs.managed.groovy.templates // tag::testcontainers-dependencies[] testImplementation libs.testcontainers.spock // end::testcontainers-dependencies[] @@ -91,6 +89,7 @@ dependencies { testFixturesApi libs.managed.spock testFixturesApi libs.managed.groovy + testFixturesApi libs.jetbrains.annotations } //tasks.withType(Test).configureEach { diff --git a/test-suite/src/test/groovy/io/micronaut/upload/browser/CreatePage.groovy b/test-suite/src/test/groovy/io/micronaut/upload/browser/CreatePage.groovy deleted file mode 100644 index 4d5e5d22527..00000000000 --- a/test-suite/src/test/groovy/io/micronaut/upload/browser/CreatePage.groovy +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2017-2020 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.upload.browser - -import geb.Page - -class CreatePage extends Page { - - static url = '/image/create' - - static at = { title == 'Create Image' } - - static content = { - uploadButton { $('input', type: 'submit', value: 'Upload') } - } - - void upload() { - uploadButton.click() - } -} diff --git a/test-suite/src/test/groovy/io/micronaut/upload/browser/FileEmptyPage.groovy b/test-suite/src/test/groovy/io/micronaut/upload/browser/FileEmptyPage.groovy deleted file mode 100644 index f8b6ee02802..00000000000 --- a/test-suite/src/test/groovy/io/micronaut/upload/browser/FileEmptyPage.groovy +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2017-2020 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.upload.browser - -import geb.Page - -class FileEmptyPage extends Page { - - static url = '/image/save' - - static at = { title == 'File is Empty' } -} diff --git a/validation/build.gradle b/validation/build.gradle index 9efa30c8d85..35c41696ca0 100644 --- a/validation/build.gradle +++ b/validation/build.gradle @@ -15,7 +15,9 @@ dependencies { api project(":core-reactive") api libs.managed.validation - compileOnly libs.managed.gorm + compileOnly(libs.managed.gorm) { + exclude(module: 'groovy') + } compileOnly project(":http-server") implementation libs.managed.reactor