Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge 4.2.x into 4.3.x #10329

Merged
merged 42 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
7f89267
fix(deps): update dependency ch.qos.logback:logback-classic to v1.4.1…
renovate[bot] Dec 3, 2023
05422bf
Update test (#10187)
sdelamo Dec 3, 2023
447f723
KSP: Resolved type arguments shouldn't be marked as a type variable (…
dstepanov Dec 4, 2023
e109642
Optimize overrides-method check (#10195)
dstepanov Dec 5, 2023
7623bc3
Fix error with duplicate builder methods (#10226)
dstepanov Dec 6, 2023
793f957
fix(deps): update dependency io.netty.incubator:netty-incubator-codec…
renovate[bot] Dec 6, 2023
c9f8158
Update ROADMAP.adoc (#10213)
sdelamo Dec 6, 2023
0530ff7
fix(deps): update dependency com.github.javaparser:javaparser-symbol-…
renovate[bot] Dec 6, 2023
34b5231
imp: don't send Content-length header for GET requests (#10218)
timyates Dec 6, 2023
fc01a73
Allow context-path to be an empty String (#10231)
jeremyg484 Dec 7, 2023
4641565
Fix concurrent retrieval of expression resolvers (#10176) (#10229)
rorueda Dec 7, 2023
88a8e8e
Change to public so that java doc is generated for Configuration Refe…
wetted Dec 7, 2023
12eaff6
KSP: Fix enum class values (#10240)
dstepanov Dec 11, 2023
edda671
docs: add reactor context propagation example (#10220)
wetted Dec 11, 2023
45b573d
KSP: Exclude static properties (#10245)
dstepanov Dec 11, 2023
36d1709
test: remove javax.persistence.Transient from Mapper (#10113)
sdelamo Dec 12, 2023
b46869e
Update breaking changes for Micronaut 4 (#10248)
hrothwell Dec 12, 2023
77d29ba
fix(deps): update dependency io.micronaut.aws:micronaut-aws-bom to v4…
renovate[bot] Dec 12, 2023
19f3d6f
KSP: Workaround for inner anonymous classes (#10247)
dstepanov Dec 12, 2023
8624397
fix(deps): update dependency io.micronaut.rxjava2:micronaut-rxjava2-b…
renovate[bot] Dec 12, 2023
2e4afbd
fix(deps): update dependency io.micronaut.reactor:micronaut-reactor-b…
renovate[bot] Dec 12, 2023
fa0b4be
Add links to guides for Micronaut Core (#10269)
wetted Dec 14, 2023
0f24d5d
Allow Refreshable scope under test for Env.FUNCTION and ANDROID (#10264)
timyates Dec 14, 2023
031568b
test. ThreadSelection accept event loop in the handler in blocking an…
sdelamo Dec 14, 2023
a6d9e97
[bug] EL fails when using primitive method arguments in expression (#…
timyates Dec 14, 2023
073d146
fix(deps): update netty monorepo to v4.1.103.final (#10270)
renovate[bot] Dec 14, 2023
b315763
fix(deps): update managed.ksp to v1.9.21-1.0.16 (#10268)
renovate[bot] Dec 14, 2023
9c19298
[skip ci] Release v4.2.2
micronaut-build Dec 14, 2023
68bd0a1
Back to 4.2.3-SNAPSHOT
micronaut-build Dec 14, 2023
bbf65a9
Fix logged errors reported by fuzzing (#10273)
yawkat Dec 15, 2023
ca177fb
KSP: Fix `@Generated` processing (#10282)
dstepanov Dec 18, 2023
1087107
Initialize classes at build time that can deadlock graal compiler (#1…
graemerocher Dec 18, 2023
7423f83
KSP: Do not store default empty string annotation value (#10284)
dstepanov Dec 18, 2023
4666825
fix(deps): update netty monorepo to v4.1.104.final (#10276)
renovate[bot] Dec 19, 2023
67e2b3d
chore(deps): update gradle/gradle-build-action action to v2.11.0 (#10…
renovate[bot] Dec 19, 2023
97aeb96
Ensure responseWritten is called on discard (#10288)
yawkat Dec 19, 2023
0295ee0
Javac: Extract type variable name using the element (#10293)
dstepanov Jan 2, 2024
f35b55b
Publish service ready / stopped in consistent order (#10325)
dstepanov Jan 4, 2024
36dcaf0
[skip ci] Release v4.2.3
micronaut-build Jan 4, 2024
bcac701
Back to 4.2.4-SNAPSHOT
micronaut-build Jan 4, 2024
77d3023
Merge branch '4.2.x' into 4.3.x
sdelamo Jan 5, 2024
2f3d519
test: StreamPressureSpec ignore on macOs
sdelamo Jan 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/corretto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
distribution: 'corretto'
java-version: ${{ matrix.java }}
- name: Setup Gradle
uses: gradle/gradle-build-action@v2.10.0
uses: gradle/gradle-build-action@v2.11.0
- name: Optional setup step
env:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
Expand Down
2 changes: 1 addition & 1 deletion ROADMAP.adoc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
= Micronaut ROADMAP

See https://github.com/micronaut-projects/micronaut-core/projects/5[Micronaut ROADMAP] for Roadmap project planning.
Micronaut Foundation uses https://github.com/orgs/micronaut-projects/projects[GitHub projects] for planning.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
@BootstrapContextCompatible
@Internal
@Order(Ordered.HIGHEST_PRECEDENCE)
final class DefaultByteBufAllocatorConfiguration implements ByteBufAllocatorConfiguration {
public final class DefaultByteBufAllocatorConfiguration implements ByteBufAllocatorConfiguration {

private static final String PROP_PREFIX = "io.netty.allocator.";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
* @since 1.0
*/
@Singleton
@Requires(notEnv = {Environment.FUNCTION, Environment.ANDROID})
@Requires(condition = RefreshScopeCondition.class)
public class RefreshScope implements CustomScope<Refreshable>, LifeCycle<RefreshScope>, ApplicationEventListener<RefreshEvent>, Ordered {

public static final int POSITION = RefreshEventListener.DEFAULT_POSITION - 100;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2017-2023 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
*
* https://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.runtime.context.scope.refresh;

import io.micronaut.context.ApplicationContext;
import io.micronaut.context.BeanContext;
import io.micronaut.context.condition.Condition;
import io.micronaut.context.condition.ConditionContext;
import io.micronaut.context.env.Environment;

import java.util.Arrays;
import java.util.Set;

/**
* As an optimization, RefreshScope is disabled for function and android environments when not under test.
*
* @author Tim Yates
* @since 4.2.2
*/
public class RefreshScopeCondition implements Condition {

private static final String[] DISABLED_ENVIRONMENTS = new String[]{Environment.FUNCTION, Environment.ANDROID};

@Override
public boolean matches(ConditionContext context) {
BeanContext beanContext = context.getBeanContext();

if (beanContext instanceof ApplicationContext applicationContext) {
Environment environment = applicationContext.getEnvironment();
Set<String> activeNames = environment.getActiveNames();

boolean disabledEnvironment = Arrays.stream(DISABLED_ENVIRONMENTS).anyMatch(activeNames::contains);
boolean isUnderTest = activeNames.contains(Environment.TEST);

if (disabledEnvironment && !isUnderTest) {
context.fail("Refresh scope is disabled for " + Environment.FUNCTION + " and " + Environment.ANDROID + " environments when not under test.");
return false;
}
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ protected void generateBytecode(ExpressionVisitorContext ctx) {
// invoke getArgument method
mv.invokeInterface(EVALUATION_CONTEXT_TYPE, GET_ARGUMENT_METHOD);
if (nodeType != null) {
mv.checkCast(nodeType);
if (TypeDescriptors.isPrimitive(nodeType)) {
mv.unbox(nodeType);
} else {
mv.checkCast(nodeType);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
# limitations under the License.
#

# DO NOT REMOVE ConversionContext and ImmutableArgumentConversionContext. See https://github.com/micronaut-projects/micronaut-core/pull/10283
Args = --initialize-at-run-time=io.micronaut.core.io.socket.SocketUtils \
--initialize-at-run-time=io.micronaut.core.type.RuntimeTypeInformation$LazyTypeInfo \
--initialize-at-build-time=io.micronaut.core.io \
--initialize-at-build-time=io.micronaut.core.optim \
--initialize-at-build-time=io.micronaut.core.util \
--initialize-at-build-time=io.micronaut.core.convert \
--initialize-at-build-time=io.micronaut.core.convert.ConversionContext \
--initialize-at-build-time=io.micronaut.core.convert.ImmutableArgumentConversionContext \
--initialize-at-build-time=io.micronaut.core.type \
--initialize-at-build-time=io.micronaut.core.annotation \
--initialize-at-build-time=io.micronaut.core.annotation.AnnotationValue \
Expand Down
21 changes: 12 additions & 9 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,22 @@ jsr107 = "1.1.1"
jsr305 = "3.0.2"
jakarta-el = "5.0.1"
jakarta-el-impl = "5.0.0-M1"
jazzer = "0.22.1"
jcache = "1.1.1"
junit5 = "5.9.3"
junit-platform="1.9.3"
logback = "1.4.13"
logback = "1.4.14"
logbook-netty = "2.16.0"
log4j = "2.22.0"
micronaut-aws = "4.1.1"
micronaut-aws = "4.2.3"
micronaut-groovy = "4.1.0"
micronaut-session = "4.1.0"
micronaut-sql = "5.3.0"
micronaut-test = "4.0.2"
micronaut-test = "4.1.1"
micronaut-validation = "4.2.0"
micronaut-rxjava2 = "2.1.0"
micronaut-rxjava2 = "2.2.0"
micronaut-rxjava3 = "3.1.0"
micronaut-reactor = "3.1.0"
micronaut-reactor = "3.2.0"
neo4j-java-driver = "5.15.0"
selenium = "4.9.1"
slf4j = "2.0.9"
Expand All @@ -65,16 +66,16 @@ managed-jackson-databind = "2.16.0"
managed-kotlin = "1.9.21"
managed-kotlin-coroutines = "1.7.3"
managed-methvin-directory-watcher = "0.18.0"
managed-netty = "4.1.101.Final"
managed-netty = "4.1.104.Final"
managed-netty-iouring = "0.0.24.Final"
managed-netty-http3 = "0.0.22.Final"
managed-netty-http3 = "0.0.23.Final"
managed-netty-tcnative = "2.0.62.Final"
managed-reactive-streams = "1.0.4"
# This should be kept aligned with https://github.com/micronaut-projects/micronaut-reactor/blob/master/gradle.properties from the BOM
managed-reactor = "3.5.11"
managed-snakeyaml = "2.0"
managed-java-parser-core = "3.25.6"
managed-ksp = "1.9.21-1.0.15"
managed-java-parser-core = "3.25.7"
managed-ksp = "1.9.21-1.0.16"
micronaut-docs = "2.0.0"

[libraries]
Expand Down Expand Up @@ -210,6 +211,8 @@ junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", vers
junit-platform-engine = { module = "org.junit.platform:junit-platform-suite-engine", version.ref = "junit-platform" }
junit-vintage = { module = "org.junit.vintage:junit-vintage-engine", version.ref = "junit5" }

jazzer-junit = { module = "com.code-intelligence:jazzer-junit", version.ref = "jazzer" }

jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "jetbrains-annotations" }

kotlin-kotest-junit5 = { module = "io.kotest:kotest-runner-junit5-jvm" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.micronaut.core.async.publisher.Publishers;
import io.micronaut.core.type.Argument;
import io.micronaut.http.HttpHeaders;
import io.micronaut.http.HttpMethod;
import io.micronaut.http.MediaType;
import io.micronaut.http.client.HttpClientConfiguration;
import io.micronaut.http.codec.MediaTypeCodec;
Expand Down Expand Up @@ -56,8 +57,14 @@ public static <I> HttpRequest.Builder builder(
) {
final HttpRequest.Builder builder = HttpRequest.newBuilder().uri(uri);
configuration.getReadTimeout().ifPresent(builder::timeout);
HttpRequest.BodyPublisher bodyPublisher = publisherForRequest(request, bodyType, mediaTypeCodecRegistry);
builder.method(request.getMethod().toString(), bodyPublisher);
if (request.getMethod() == HttpMethod.GET) {
builder.GET();
} else if (request.getMethod() == HttpMethod.DELETE) {
builder.DELETE();
} else {
HttpRequest.BodyPublisher bodyPublisher = publisherForRequest(request, bodyType, mediaTypeCodecRegistry);
builder.method(request.getMethod().toString(), bodyPublisher);
}
request.getHeaders().forEach((name, values) -> values.forEach(value -> builder.header(name, value)));
if (request.getContentType().isEmpty()) {
builder.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2017-2023 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
*
* https://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.http.client.tck.tests;

import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled;
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled;
import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation;

/**
* A condition that enables or disables a test based on the presence of the {@link ClientDisabled} annotation.
* <p>
* The condition is enabled by default, unless the annotation is present and the {@link ClientDisabled#jdk()} or
* {@link ClientDisabled#httpClient()} parameters match the current JDK version and the HTTP client configuration
* parameter.
*/
public class ClientDisabledCondition implements ExecutionCondition {

public static final String JDK = "jdk";
public static final String NETTY = "netty";
public static final String HTTP_CLIENT_CONFIGURATION = "httpClient";

private static final ConditionEvaluationResult ENABLED_BY_DEFAULT = enabled("@ClientDisabled is not present");
private static final ConditionEvaluationResult ENABLED = enabled("Enabled");
private static final ConditionEvaluationResult DISABLED = disabled("Disabled");

private static boolean jdkMajorVersionMatches(ClientDisabled d) {
return Integer.toString(Runtime.version().feature()).equals(d.jdk());
}

private static boolean clientParameterMatches(ExtensionContext context, ClientDisabled d) {
return context.getConfigurationParameter(HTTP_CLIENT_CONFIGURATION).orElse("").equalsIgnoreCase(d.httpClient());
}

@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
return findAnnotation(context.getElement(), ClientDisabled.class)
.map(d -> clientParameterMatches(context, d) && jdkMajorVersionMatches(d)
? DISABLED
: ENABLED)
.orElse(ENABLED_BY_DEFAULT);
}

/**
* Annotation that can be used to disable a test based on the JDK version and the HTTP client configuration.
*/
@Documented
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(ClientDisabledCondition.class)
public @interface ClientDisabled {

String httpClient() default "";

String jdk() default "";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright 2017-2023 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
*
* https://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.http.client.tck.tests;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import io.micronaut.context.ApplicationContext;
import io.micronaut.core.io.socket.SocketUtils;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.MutableHttpRequest;
import io.micronaut.http.client.HttpClient;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URL;

import static io.micronaut.http.HttpHeaders.CONTENT_LENGTH;
import static org.junit.jupiter.api.Assertions.assertEquals;

class ContentLengthHeaderTest {

private static final String PATH = "/content-length";

private HttpServer server;

private ApplicationContext applicationContext;
private HttpClient httpClient;

@BeforeEach
void setUp() throws IOException {
server = HttpServer.create(new InetSocketAddress(SocketUtils.findAvailableTcpPort()), 0);
server.setExecutor(java.util.concurrent.Executors.newCachedThreadPool());
server.createContext(PATH, new MyHandler());
server.start();

applicationContext = ApplicationContext.run();
httpClient = applicationContext.createBean(HttpClient.class, new URL("http://localhost:" + server.getAddress().getPort()));
}

@AfterEach
void tearDown() {
if (server != null) {
server.stop(0);
}
applicationContext.stop();
}

@ParameterizedTest(name = "blocking={0}")
@ValueSource(booleans = {true, false})
void postContainsHeader(boolean blocking) {
MutableHttpRequest<String> post = HttpRequest.POST(PATH, "tim");
String retrieve = blocking
? httpClient.toBlocking().retrieve(post)
: Flux.from(httpClient.retrieve(post)).blockFirst();
assertEquals("POST:3", retrieve);
}

@ParameterizedTest(name = "blocking={0}")
@ValueSource(booleans = {true, false})
@ClientDisabledCondition.ClientDisabled(httpClient = ClientDisabledCondition.JDK, jdk = "17") // The bug is fixed in the JDK HttpClient 21, so we disable the test for prior versions
void getContainsHeader(boolean blocking) {
MutableHttpRequest<String> get = HttpRequest.GET(PATH);
String retrieve = blocking
? httpClient.toBlocking().retrieve(get)
: Flux.from(httpClient.retrieve(get)).blockFirst();
assertEquals("GET:", retrieve);
}

static class MyHandler implements HttpHandler {

private String header(Headers requestHeaders, String name) {
if (requestHeaders.containsKey(name)) {
return String.join(", ", requestHeaders.get(name));
} else {
return "";
}
}

@Override
public void handle(HttpExchange exchange) throws IOException {
String method = exchange.getRequestMethod();
String contentLength = header(exchange.getRequestHeaders(), CONTENT_LENGTH);
exchange.sendResponseHeaders(200, 0);
try (var os = exchange.getResponseBody()) {
os.write("%s:%s".formatted(method, contentLength).getBytes());
}
exchange.close();
}
}
}
Loading
Loading