Skip to content

Commit 4943774

Browse files
authored
Updates to Helidon Common, Part 2 (helidon-io#4718)
Preparation for Loom based server. Changes to common, common HTTP, common media types and fixes in all impacted modules.
1 parent 3d6499c commit 4943774

790 files changed

Lines changed: 20135 additions & 11490 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,10 @@ We are pleased to announce Helidon 4.0.0 a major release that includes significa
2323
- Introduction of `@Weight`, `Weighted` and `Weights` instead of `@Priority` and `Prioritized`, to base ordering on a double (allows to fit a component between any other two components), all modules using priority are refactored (except for MicroProfile where required by specifications).
2424
- higher weight means a component is more important
2525
- moved priority related types to MP config (as that is the lowest level MP module)
26-
- replaces all instances in SE that use priority with weight (no dependency on Jakarta, predictible and easy to understand behavior)
26+
- replaces all instances in SE that use priority with weight (no dependency on Jakarta, predictible and easy to understand behavior)
27+
- Introduction of `MediaType` as the abstraction of any media type, as used by Config, static content and HTTP in general. See `MediaType` and `MediaTypes`
28+
- `MapperManager` now supports mapping qualifiers
29+
- new `helidon-common-parameters` module contains an abstraction of a container that has named values (one or more); this is used in path parameters, query parameters, form parameters etc.
30+
- new `helidon-common-uri` module contains URI abstraction (path with possible parameters, query, and fragment)
31+
- Header processing now uses `HeaderName` and `HeaderValue` types. This allows you to prepare constants with custom names and values that
32+
are often reused. It also allows us to improve parsing speed of HTTP requests.

applications/pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
<properties>
4141
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
4242
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
43-
<maven.compiler.source>17</maven.compiler.source>
43+
<maven.compiler.source>19</maven.compiler.source>
4444
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
4545
<maven.compiler.release>${maven.compiler.source}</maven.compiler.release>
4646
<version.plugin.compiler>3.8.1</version.plugin.compiler>
@@ -81,6 +81,7 @@
8181
<systemPropertyVariables>
8282
<java.util.logging.config.file>${project.build.outputDirectory}/logging.properties</java.util.logging.config.file>
8383
</systemPropertyVariables>
84+
<argLine>--enable-preview</argLine>
8485
</configuration>
8586
</plugin>
8687
<plugin>
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
3-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4-
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
5-
http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
6-
version="2.0"
7-
bean-discovery-mode="annotated">
8-
</beans>
2+
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
5+
https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd"
6+
version="3.0"
7+
bean-discovery-mode="annotated">
8+
</beans>

archetypes/helidon/src/main/archetype/mp/custom/files/src/test/java/__pkg__/TestCORS.java.mustache

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package {{package}};
22

33
import io.helidon.common.http.Headers;
4+
import io.helidon.common.http.Http;
45
import io.helidon.config.Config;
56
import io.helidon.microprofile.server.Server;
67
import io.helidon.webclient.WebClient;
78
import io.helidon.webclient.WebClientRequestBuilder;
9+
import io.helidon.webclient.WebClientRequestHeaders;
810
import io.helidon.webclient.WebClientResponse;
11+
import io.helidon.webclient.WebClientResponseHeaders;
912
import io.helidon.webserver.cors.CrossOriginConfig;
1013
import org.junit.jupiter.api.AfterAll;
1114
import org.junit.jupiter.api.BeforeAll;
@@ -49,55 +52,56 @@ public class TestCORS {
4952
@Test
5053
void testAnonymousGreetWithCors() {
5154
WebClientRequestBuilder builder = client.get();
52-
Headers headers = builder.headers();
53-
headers.add("Origin", "http://foo.com");
54-
headers.add("Host", "here.com");
55+
WebClientRequestHeaders headers = builder.headers();
56+
headers.set(Http.Header.ORIGIN, "http://foo.com");
57+
headers.set(Http.Header.HOST, "here.com");
5558
5659
WebClientResponse r = getResponse(builder);
5760
assertThat("HTTP response", r.status().code(), is(200));
5861
String payload = fromPayload(r);
59-
assertThat("HTTP response payload", payload, is("{\"message\":\"Hello World!\"}"));
60-
headers = r.headers();
61-
Optional<String> allowOrigin = headers.value(CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN);
62+
assertThat("HTTP response payload", payload, is("{\"message\":\"Hello World!\"}"));
63+
WebClientResponseHeaders resHeaders = r.headers();
64+
Optional<String> allowOrigin = resHeaders.value(Http.Header.ACCESS_CONTROL_ALLOW_ORIGIN);
6265
assertThat("Expected CORS header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN + " is present",
6366
allowOrigin.isPresent(), is(true));
64-
assertThat("CORS header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN, allowOrigin.get(), is("http://foo.com"));
67+
assertThat("CORS header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN, allowOrigin.get(), is("*"));
6568
}
6669

6770
@Test
6871
void testCustomGreetingWithCors() {
6972
7073
WebClientRequestBuilder builder = client.method("OPTIONS");
71-
Headers headers = builder.headers();
72-
headers.add("Origin", "http://foo.com");
73-
headers.add("Host", "here.com");
74+
WebClientRequestHeaders headers = builder.headers();
75+
headers.set(Http.Header.ORIGIN, "http://foo.com");
76+
headers.set(Http.Header.HOST, "here.com");
7477
headers.add("Access-Control-Request-Method", "PUT");
7578
7679
WebClientResponse r = builder.path("/simple-greet")
7780
.submit()
7881
.await();
7982
8083
assertThat("pre-flight status", r.status().code(), is(200));
81-
Headers preflightResponseHeaders = r.headers();
82-
List<String> allowMethods = preflightResponseHeaders.values(CrossOriginConfig.ACCESS_CONTROL_ALLOW_METHODS);
84+
WebClientResponseHeaders responseHeaders = r.headers();
85+
Headers preflightResponseHeaders = responseHeaders;
86+
List<String> allowMethods = preflightResponseHeaders.values(Http.Header.ACCESS_CONTROL_ALLOW_METHODS);
8387
assertThat("pre-flight response check for " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_METHODS,
8488
allowMethods, is(not(empty())));
8589
assertThat("Header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_METHODS, allowMethods, contains("PUT"));
86-
List<String> allowOrigins = preflightResponseHeaders.values(CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN);
90+
List<String> allowOrigins = preflightResponseHeaders.values(Http.Header.ACCESS_CONTROL_ALLOW_ORIGIN);
8791
assertThat("pre-flight response check for " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN,
8892
allowOrigins, is(not(empty())));
8993
assertThat( "Header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN, allowOrigins, contains("http://foo.com"));
9094
9195
builder = client.put();
9296
headers = builder.headers();
93-
headers.add("Origin", "http://foo.com");
94-
headers.add("Host", "here.com");
97+
headers.set(Http.Header.ORIGIN, "http://foo.com");
98+
headers.set(Http.Header.HOST, "here.com");
9599
headers.addAll(preflightResponseHeaders);
96100
97101
r = putResponse("Cheers", builder);
98102
assertThat("HTTP response3", r.status().code(), is(200));
99-
headers = r.headers();
100-
allowOrigins = headers.values(CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN);
103+
responseHeaders = r.headers();
104+
allowOrigins = headers.values(Http.Header.ACCESS_CONTROL_ALLOW_ORIGIN);
101105
assertThat("Expected CORS header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN,
102106
allowOrigins, is(not(empty())));
103107
assertThat( "Header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN, allowOrigins, contains("http://foo.com"));
@@ -107,9 +111,9 @@ public class TestCORS {
107111
@Test
108112
void testGreetingChangeWithCorsAndOtherOrigin() {
109113
WebClientRequestBuilder builder = client.put();
110-
Headers headers = builder.headers();
111-
headers.add("Origin", "http://other.com");
112-
headers.add("Host", "here.com");
114+
WebClientRequestHeaders headers = builder.headers();
115+
headers.set(Http.Header.ORIGIN, "http://other.com");
116+
headers.set(Http.Header.HOST, "here.com");
113117
114118
WebClientResponse r = putResponse("Ahoy", builder);
115119
boolean isOverriding = Config.create().get("cors").exists();

archetypes/helidon/src/main/archetype/se/custom/files/src/main/java/__pkg__/FileService.java.multipart.mustache

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11

22
package {{package}};
33

4+
import java.nio.file.Path;
5+
import java.util.Arrays;
6+
import java.util.Map;
7+
import java.util.concurrent.ExecutorService;
8+
49
import io.helidon.common.configurable.ThreadPoolSupplier;
10+
import io.helidon.common.http.ContentDisposition;
511
import io.helidon.common.http.DataChunk;
612
import io.helidon.common.http.Http;
7-
import io.helidon.common.http.MediaType;
13+
import io.helidon.common.media.type.MediaTypes;
814
import io.helidon.common.reactive.IoMulti;
9-
import io.helidon.media.multipart.ContentDisposition;
1015
import io.helidon.media.multipart.ReadableBodyPart;
1116
import io.helidon.webserver.ResponseHeaders;
1217
import io.helidon.webserver.Routing;
1318
import io.helidon.webserver.ServerRequest;
1419
import io.helidon.webserver.ServerResponse;
1520
import io.helidon.webserver.Service;
21+
1622
import jakarta.json.Json;
1723
import jakarta.json.JsonArrayBuilder;
1824
import jakarta.json.JsonBuilderFactory;
1925

20-
import java.nio.file.Path;
21-
import java.util.Arrays;
22-
import java.util.Map;
23-
import java.util.concurrent.ExecutorService;
24-
2526
/**
2627
* File service.
2728
*/
@@ -55,8 +56,8 @@ public final class FileService implements Service {
5556
private void download(ServerRequest req, ServerResponse res) {
5657
Path filePath = storage.lookup(req.path().param("fname"));
5758
ResponseHeaders headers = res.headers();
58-
headers.contentType(MediaType.APPLICATION_OCTET_STREAM);
59-
headers.put(Http.Header.CONTENT_DISPOSITION, ContentDisposition.builder()
59+
headers.contentType(MediaTypes.APPLICATION_OCTET_STREAM);
60+
headers.set(Http.Header.CONTENT_DISPOSITION, ContentDisposition.builder()
6061
.filename(filePath.getFileName().toString())
6162
.build()
6263
.toString());

archetypes/helidon/src/main/archetype/se/custom/files/src/test/java/__pkg__/FileServiceTest.java.multipart.mustache

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11

22
package {{package}};
33

4-
import io.helidon.common.http.MediaType;
4+
import java.io.IOException;
5+
import java.nio.charset.StandardCharsets;
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.util.List;
9+
import java.util.concurrent.TimeUnit;
10+
11+
import io.helidon.common.http.Http;
12+
import io.helidon.common.media.type.MediaTypes;
513
import io.helidon.media.jsonp.JsonpSupport;
614
import io.helidon.media.multipart.FileFormParams;
715
import io.helidon.media.multipart.MultiPartSupport;
816
import io.helidon.webclient.WebClient;
917
import io.helidon.webclient.WebClientResponse;
1018
import io.helidon.webserver.WebServer;
19+
1120
import jakarta.json.JsonObject;
1221
import jakarta.json.JsonString;
1322
import org.hamcrest.Matchers;
@@ -18,13 +27,6 @@ import org.junit.jupiter.api.Order;
1827
import org.junit.jupiter.api.Test;
1928
import org.junit.jupiter.api.TestMethodOrder;
2029

21-
import java.io.IOException;
22-
import java.nio.charset.StandardCharsets;
23-
import java.nio.file.Files;
24-
import java.nio.file.Path;
25-
import java.util.List;
26-
import java.util.concurrent.TimeUnit;
27-
2830
import static org.hamcrest.CoreMatchers.containsString;
2931
import static org.hamcrest.CoreMatchers.is;
3032
import static org.hamcrest.MatcherAssert.assertThat;
@@ -65,7 +67,7 @@ public class FileServiceTest {
6567
Path file = Files.write( Files.createTempFile(null, null), "bar\n".getBytes(StandardCharsets.UTF_8));
6668
WebClientResponse response = webClient
6769
.post()
68-
.contentType(MediaType.MULTIPART_FORM_DATA)
70+
.contentType(MediaTypes.MULTIPART_FORM_DATA)
6971
.submit(FileFormParams.builder()
7072
.addFile("file[]", "foo.txt", file)
7173
.build())
@@ -81,7 +83,7 @@ public class FileServiceTest {
8183
WebClientResponse response = webClient
8284
.post()
8385
.queryParam("stream", "true")
84-
.contentType(MediaType.MULTIPART_FORM_DATA)
86+
.contentType(MediaTypes.MULTIPART_FORM_DATA)
8587
.submit(FileFormParams.builder()
8688
.addFile("file[]", "streamed-foo.txt", file)
8789
.addFile("otherPart", "streamed-foo2.txt", file2)
@@ -95,7 +97,7 @@ public class FileServiceTest {
9597
public void testList() {
9698
WebClientResponse response = webClient
9799
.get()
98-
.contentType(MediaType.APPLICATION_JSON)
100+
.contentType(MediaTypes.APPLICATION_JSON)
99101
.request()
100102
.await();
101103
assertThat(response.status().code(), Matchers.is(200));
@@ -111,11 +113,11 @@ public class FileServiceTest {
111113
WebClientResponse response = webClient
112114
.get()
113115
.path("foo.txt")
114-
.accept(MediaType.APPLICATION_OCTET_STREAM)
116+
.accept(MediaTypes.APPLICATION_OCTET_STREAM)
115117
.request()
116118
.await();
117119
assertThat(response.status().code(), is(200));
118-
assertThat(response.headers().first("Content-Disposition").orElse(null),
120+
assertThat(response.headers().first(Http.Header.CONTENT_DISPOSITION).orElse(null),
119121
containsString("filename=\"foo.txt\""));
120122
byte[] bytes = response.content().as(byte[].class).await();
121123
assertThat(new String(bytes, StandardCharsets.UTF_8), Matchers.is("bar\n"));

archetypes/helidon/src/main/archetype/se/custom/files/src/test/java/__pkg__/TestCORS.java.mustache

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package {{package}};
22

33
import io.helidon.common.http.Headers;
4+
import io.helidon.common.http.Http;
45
import io.helidon.config.Config;
56
import io.helidon.webclient.WebClient;
67
import io.helidon.webclient.WebClientRequestBuilder;
8+
import io.helidon.webclient.WebClientRequestHeaders;
79
import io.helidon.webclient.WebClientResponse;
10+
import io.helidon.webclient.WebClientResponseHeaders;
811
import io.helidon.webserver.WebServer;
912
import io.helidon.webserver.cors.CrossOriginConfig;
1013
import org.junit.jupiter.api.AfterAll;
@@ -58,16 +61,16 @@ public class TestCORS {
5861
@Test
5962
void testAnonymousGreetWithCors() {
6063
WebClientRequestBuilder builder = client.get();
61-
Headers headers = builder.headers();
62-
headers.add("Origin", "http://foo.com");
63-
headers.add("Host", "here.com");
64+
WebClientRequestHeaders headers = builder.headers();
65+
headers.set(Http.Header.ORIGIN, "http://foo.com");
66+
headers.set(Http.Header.HOST, "here.com");
6467
6568
WebClientResponse r = getResponse(builder);
6669
assertThat("HTTP response", r.status().code(), is(200));
6770
String payload = fromPayload(r);
6871
assertThat("HTTP response payload", payload, is("Hello World!"));
69-
headers = r.headers();
70-
Optional<String> allowOrigin = headers.value(CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN);
72+
WebClientResponseHeaders resHeaders = r.headers();
73+
Optional<String> allowOrigin = resHeaders.value(Http.Header.ACCESS_CONTROL_ALLOW_ORIGIN);
7174
assertThat("Expected CORS header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN + " is present",
7275
allowOrigin.isPresent(), is(true));
7376
assertThat("CORS header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN, allowOrigin.get(), is("*"));
@@ -77,36 +80,37 @@ public class TestCORS {
7780
void testCustomGreetingWithCors() {
7881
7982
WebClientRequestBuilder builder = client.method("OPTIONS");
80-
Headers headers = builder.headers();
81-
headers.add("Origin", "http://foo.com");
82-
headers.add("Host", "here.com");
83+
WebClientRequestHeaders headers = builder.headers();
84+
headers.set(Http.Header.ORIGIN, "http://foo.com");
85+
headers.set(Http.Header.HOST, "here.com");
8386
headers.add("Access-Control-Request-Method", "PUT");
8487
8588
WebClientResponse r = builder.path("/cors")
8689
.submit()
8790
.await();
8891
8992
assertThat("pre-flight status", r.status().code(), is(200));
90-
Headers preflightResponseHeaders = r.headers();
91-
List<String> allowMethods = preflightResponseHeaders.values(CrossOriginConfig.ACCESS_CONTROL_ALLOW_METHODS);
93+
WebClientResponseHeaders responseHeaders = r.headers();
94+
Headers preflightResponseHeaders = responseHeaders;
95+
List<String> allowMethods = preflightResponseHeaders.values(Http.Header.ACCESS_CONTROL_ALLOW_METHODS);
9296
assertThat("pre-flight response check for " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_METHODS,
9397
allowMethods, is(not(empty())));
9498
assertThat("Header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_METHODS, allowMethods, contains("PUT"));
95-
List<String> allowOrigins = preflightResponseHeaders.values(CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN);
99+
List<String> allowOrigins = preflightResponseHeaders.values(Http.Header.ACCESS_CONTROL_ALLOW_ORIGIN);
96100
assertThat("pre-flight response check for " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN,
97101
allowOrigins, is(not(empty())));
98102
assertThat( "Header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN, allowOrigins, contains("http://foo.com"));
99103
100104
builder = client.put();
101105
headers = builder.headers();
102-
headers.add("Origin", "http://foo.com");
103-
headers.add("Host", "here.com");
106+
headers.set(Http.Header.ORIGIN, "http://foo.com");
107+
headers.set(Http.Header.HOST, "here.com");
104108
headers.addAll(preflightResponseHeaders);
105109
106110
r = putResponse("Cheers", builder);
107111
assertThat("HTTP response3", r.status().code(), is(200));
108-
headers = r.headers();
109-
allowOrigins = headers.values(CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN);
112+
responseHeaders = r.headers();
113+
allowOrigins = headers.values(Http.Header.ACCESS_CONTROL_ALLOW_ORIGIN);
110114
assertThat("Expected CORS header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN,
111115
allowOrigins, is(not(empty())));
112116
assertThat( "Header " + CrossOriginConfig.ACCESS_CONTROL_ALLOW_ORIGIN, allowOrigins, contains("http://foo.com"));
@@ -116,9 +120,9 @@ public class TestCORS {
116120
@Test
117121
void testGreetingChangeWithCorsAndOtherOrigin() {
118122
WebClientRequestBuilder builder = client.put();
119-
Headers headers = builder.headers();
120-
headers.add("Origin", "http://other.com");
121-
headers.add("Host", "here.com");
123+
WebClientRequestHeaders headers = builder.headers();
124+
headers.set(Http.Header.ORIGIN, "http://other.com");
125+
headers.set(Http.Header.HOST, "here.com");
122126
123127
WebClientResponse r = putResponse("Ahoy", builder);
124128
boolean isOverriding = Config.create().get("cors").exists();

archetypes/helidon/src/main/archetype/se/database/files/src/main/java/__pkg__/PokemonMapperProvider.java.mustache

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ import java.util.List;
77
import java.util.Map;
88
import java.util.Optional;
99

10-
import jakarta.annotation.Priority;
11-
10+
import io.helidon.common.Weight;
1211
import io.helidon.dbclient.DbColumn;
1312
import io.helidon.dbclient.DbMapper;
1413
import io.helidon.dbclient.DbRow;
@@ -19,7 +18,7 @@ import io.helidon.dbclient.spi.DbMapperProvider;
1918
*
2019
* Pokemon, and Pokemon character names are trademarks of Nintendo.
2120
*/
22-
@Priority(1000)
21+
@Weight(50)
2322
public class PokemonMapperProvider implements DbMapperProvider {
2423
private static final PokemonMapper MAPPER = new PokemonMapper();
2524

0 commit comments

Comments
 (0)