This is an automated email from the ASF dual-hosted git repository. bchapuis pushed a commit to branch armeria in repository https://gitbox.apache.org/repos/asf/incubator-baremaps.git
commit 8d040716b57d9527ad503f534b1a3e7fa8cac102 Author: Bertil Chapuis <[email protected]> AuthorDate: Sun Jan 14 09:26:46 2024 +0100 Enable armeria in dev mode --- .../main/java/org/apache/baremaps/cli/map/Dev.java | 67 +++++++++++----------- baremaps-server/pom.xml | 8 +++ .../org/apache/baremaps/server/ChangeResource.java | 49 ++++++---------- .../org/apache/baremaps/server/StyleResource.java | 15 ++--- .../apache/baremaps/server/TileJSONResource.java | 15 ++--- .../org/apache/baremaps/server/TileResource.java | 38 ++++++------ .../apache/baremaps/server/TilesetResource.java | 15 ++--- pom.xml | 11 ++++ 8 files changed, 98 insertions(+), 120 deletions(-) diff --git a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Dev.java b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Dev.java index dc85e334..f335ab6b 100644 --- a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Dev.java +++ b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Dev.java @@ -17,27 +17,29 @@ package org.apache.baremaps.cli.map; -import static io.servicetalk.data.jackson.jersey.ServiceTalkJacksonSerializerFeature.newContextResolver; import static org.apache.baremaps.utils.ObjectMapperUtils.objectMapper; -import io.servicetalk.http.netty.HttpServers; -import io.servicetalk.http.router.jersey.HttpJerseyRouterBuilder; +import com.linecorp.armeria.common.HttpMethod; +import com.linecorp.armeria.server.Server; +import com.linecorp.armeria.server.annotation.JacksonResponseConverterFunction; +import com.linecorp.armeria.server.cors.CorsService; +import com.linecorp.armeria.server.file.FileService; import java.io.IOException; import java.nio.file.Path; import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; + +import com.linecorp.armeria.server.file.HttpFile; import org.apache.baremaps.cli.Options; import org.apache.baremaps.config.ConfigReader; import org.apache.baremaps.server.*; -import org.apache.baremaps.server.CorsFilter; import org.apache.baremaps.tilestore.TileStore; import org.apache.baremaps.tilestore.postgres.PostgresTileStore; import org.apache.baremaps.utils.PostgresUtils; import org.apache.baremaps.vectortile.style.Style; import org.apache.baremaps.vectortile.tileset.Tileset; import org.glassfish.hk2.api.TypeLiteral; -import org.glassfish.hk2.utilities.binding.AbstractBinder; -import org.glassfish.jersey.server.ResourceConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import picocli.CommandLine.Command; @@ -88,7 +90,6 @@ public class Dev implements Callable<Integer> { } }; - var styleSupplierType = new TypeLiteral<Supplier<Style>>() {}; var styleSupplier = (Supplier<Style>) () -> { try { var config = configReader.read(stylePath); @@ -98,7 +99,6 @@ public class Dev implements Callable<Integer> { } }; - var tileJSONSupplierType = new TypeLiteral<Supplier<Tileset>>() {}; var tileJSONSupplier = (Supplier<Tileset>) () -> { try { var config = configReader.read(tilesetPath); @@ -108,33 +108,30 @@ public class Dev implements Callable<Integer> { } }; - var application = new ResourceConfig() - .register(CorsFilter.class) - .register(ChangeResource.class) - .register(TileResource.class) - .register(StyleResource.class) - .register(TilesetResource.class) - .register(ChangeResource.class) - .register(ClassPathResource.class) - .register(newContextResolver(objectMapper)) - .register(new AbstractBinder() { - @Override - protected void configure() { - bind("assets").to(String.class).named("directory"); - bind("viewer.html").to(String.class).named("index"); - bind(tilesetPath).to(Path.class).named("tileset"); - bind(stylePath).to(Path.class).named("style"); - bind(tileStoreSupplier).to(tileStoreType); - bind(styleSupplier).to(styleSupplierType); - bind(tileJSONSupplier).to(tileJSONSupplierType); - } - }); - - var httpService = new HttpJerseyRouterBuilder().buildBlockingStreaming(application); - var serverContext = HttpServers.forPort(port).listenBlockingStreamingAndAwait(httpService); - - logger.info("Listening on {}", serverContext.listenAddress()); - serverContext.awaitShutdown(); + var serverBuilder = Server.builder(); + serverBuilder.http(port); + + JacksonResponseConverterFunction jsonResponseConverter = new JacksonResponseConverterFunction(objectMapper); + serverBuilder.annotatedService(new ChangeResource(tilesetPath, stylePath), jsonResponseConverter); + serverBuilder.annotatedService(new TileResource(tileStoreSupplier), jsonResponseConverter); + serverBuilder.annotatedService(new StyleResource(styleSupplier), jsonResponseConverter); + serverBuilder.annotatedService(new TilesetResource(tileJSONSupplier), jsonResponseConverter); + + HttpFile index = HttpFile.of(ClassLoader.getSystemClassLoader(), "/assets/viewer.html"); + serverBuilder.service("/", index.asService()); + serverBuilder.serviceUnder("/", FileService.of(ClassLoader.getSystemClassLoader(), "/assets")); + + serverBuilder.decorator(CorsService.builderForAnyOrigin() + .allowRequestMethods(HttpMethod.POST, HttpMethod.GET, HttpMethod.PUT) + .allowRequestHeaders("Origin", "Content-Type", "Accept") + .newDecorator()); + + serverBuilder.disableServerHeader(); + serverBuilder.disableDateHeader(); + + Server server = serverBuilder.build(); + CompletableFuture<Void> future = server.start(); + future.join(); return 0; } diff --git a/baremaps-server/pom.xml b/baremaps-server/pom.xml index 291e6b72..8ebd29dd 100644 --- a/baremaps-server/pom.xml +++ b/baremaps-server/pom.xml @@ -26,6 +26,14 @@ limitations under the License. <artifactId>baremaps-server</artifactId> <dependencies> + <dependency> + <groupId>com.linecorp.armeria</groupId> + <artifactId>armeria</artifactId> + </dependency> + <dependency> + <groupId>com.linecorp.armeria</groupId> + <artifactId>armeria-reactor3</artifactId> + </dependency> <dependency> <groupId>io.servicetalk</groupId> <artifactId>servicetalk-http-api</artifactId> diff --git a/baremaps-server/src/main/java/org/apache/baremaps/server/ChangeResource.java b/baremaps-server/src/main/java/org/apache/baremaps/server/ChangeResource.java index 0b714edb..ebd80eee 100644 --- a/baremaps-server/src/main/java/org/apache/baremaps/server/ChangeResource.java +++ b/baremaps-server/src/main/java/org/apache/baremaps/server/ChangeResource.java @@ -22,28 +22,21 @@ import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.linecorp.armeria.common.sse.ServerSentEvent; +import com.linecorp.armeria.server.ServiceRequestContext; +import com.linecorp.armeria.server.annotation.Get; +import com.linecorp.armeria.server.annotation.ProducesEventStream; import java.io.IOException; import java.nio.file.*; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; -import javax.ws.rs.GET; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.sse.OutboundSseEvent; -import javax.ws.rs.sse.Sse; -import javax.ws.rs.sse.SseBroadcaster; -import javax.ws.rs.sse.SseEventSink; import org.apache.baremaps.config.ConfigReader; -import org.jvnet.hk2.annotations.Optional; +import org.reactivestreams.Publisher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import reactor.core.publisher.Sinks; /** * A resource that provides the changes in the tileset and style. */ -@Singleton [email protected]("/") public class ChangeResource { private static final Logger logger = LoggerFactory.getLogger(ChangeResource.class); @@ -56,40 +49,30 @@ public class ChangeResource { private final Path style; - private final SseBroadcaster sseBroadcaster; - - private final OutboundSseEvent.Builder sseEventBuilder; + private final Sinks.Many<ServerSentEvent> changes = Sinks.many().multicast().directBestEffort(); /** * Constructs a {@code ChangeResource}. * * @param tileset the path to the tileset * @param style the path to the style - * @param sse the server-sent events */ - @Inject - public ChangeResource( - @Named("tileset") @Optional Path tileset, - @Named("style") @Optional Path style, - Sse sse) { + public ChangeResource(Path tileset, Path style) { this.tileset = tileset; this.style = style; - this.sseBroadcaster = sse.newBroadcaster(); - this.sseEventBuilder = sse.newEventBuilder(); - var changeListener = new ChangeListener(); - new Thread(changeListener).start(); + new Thread(new ChangeListener()).start(); } /** * Returns the changes in the tileset and style. * - * @param sseEventSink the server-sent events + * @param ctx the service request context */ - @GET - @javax.ws.rs.Path("changes") - @Produces("text/event-stream") - public void changes(@Context SseEventSink sseEventSink) { - sseBroadcaster.register(sseEventSink); + @Get("/changes") + @ProducesEventStream + public Publisher<ServerSentEvent> changes(ServiceRequestContext ctx) { + ctx.clearRequestTimeout(); + return changes.asFlux(); } /** @@ -127,7 +110,7 @@ public class ChangeResource { } // broadcast the changes - sseBroadcaster.broadcast(sseEventBuilder.data(styleObjectNode.toString()).build()); + changes.tryEmitNext(ServerSentEvent.ofData(styleObjectNode.toString())); } } key.reset(); diff --git a/baremaps-server/src/main/java/org/apache/baremaps/server/StyleResource.java b/baremaps-server/src/main/java/org/apache/baremaps/server/StyleResource.java index 4302e5b1..2e25245a 100644 --- a/baremaps-server/src/main/java/org/apache/baremaps/server/StyleResource.java +++ b/baremaps-server/src/main/java/org/apache/baremaps/server/StyleResource.java @@ -17,31 +17,24 @@ package org.apache.baremaps.server; +import com.linecorp.armeria.server.annotation.Get; +import com.linecorp.armeria.server.annotation.ProducesJson; import java.util.function.Supplier; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.ws.rs.GET; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; import org.apache.baremaps.vectortile.style.Style; /** * A resource that provides access to the style. */ -@Singleton [email protected]("/") public class StyleResource { private final Supplier<Style> styleSupplier; - @Inject public StyleResource(Supplier<Style> styleSupplier) { this.styleSupplier = styleSupplier; } - @GET - @javax.ws.rs.Path("style.json") - @Produces(MediaType.APPLICATION_JSON) + @Get("/style.json") + @ProducesJson public Style getStyle() { return styleSupplier.get(); } diff --git a/baremaps-server/src/main/java/org/apache/baremaps/server/TileJSONResource.java b/baremaps-server/src/main/java/org/apache/baremaps/server/TileJSONResource.java index 396328c8..321a0f31 100644 --- a/baremaps-server/src/main/java/org/apache/baremaps/server/TileJSONResource.java +++ b/baremaps-server/src/main/java/org/apache/baremaps/server/TileJSONResource.java @@ -17,31 +17,24 @@ package org.apache.baremaps.server; +import com.linecorp.armeria.server.annotation.Get; +import com.linecorp.armeria.server.annotation.ProducesJson; import java.util.function.Supplier; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.ws.rs.GET; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; import org.apache.baremaps.vectortile.tilejson.TileJSON; /** * A resource that provides access to the tileJSON file. */ -@Singleton [email protected]("/") public class TileJSONResource { private final Supplier<TileJSON> tileJSONSupplier; - @Inject public TileJSONResource(Supplier<TileJSON> tileJSONSupplier) { this.tileJSONSupplier = tileJSONSupplier; } - @GET - @javax.ws.rs.Path("tiles.json") - @Produces(MediaType.APPLICATION_JSON) + @Get("/tiles.json") + @ProducesJson public TileJSON getTileset() { return tileJSONSupplier.get(); } diff --git a/baremaps-server/src/main/java/org/apache/baremaps/server/TileResource.java b/baremaps-server/src/main/java/org/apache/baremaps/server/TileResource.java index bb074b94..964ac158 100644 --- a/baremaps-server/src/main/java/org/apache/baremaps/server/TileResource.java +++ b/baremaps-server/src/main/java/org/apache/baremaps/server/TileResource.java @@ -19,13 +19,14 @@ package org.apache.baremaps.server; import static com.google.common.net.HttpHeaders.*; +import com.linecorp.armeria.common.HttpData; +import com.linecorp.armeria.common.HttpResponse; +import com.linecorp.armeria.common.ResponseHeaders; +import com.linecorp.armeria.server.annotation.Blocking; +import com.linecorp.armeria.server.annotation.Get; +import com.linecorp.armeria.server.annotation.Param; import java.nio.ByteBuffer; import java.util.function.Supplier; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.ws.rs.GET; -import javax.ws.rs.PathParam; -import javax.ws.rs.core.Response; import org.apache.baremaps.tilestore.TileCoord; import org.apache.baremaps.tilestore.TileStore; import org.apache.baremaps.tilestore.TileStoreException; @@ -35,8 +36,6 @@ import org.slf4j.LoggerFactory; /** * A resource that provides access to the tiles. */ -@Singleton [email protected]("/") public class TileResource { private static final Logger logger = LoggerFactory.getLogger(TileResource.class); @@ -47,33 +46,34 @@ public class TileResource { private final Supplier<TileStore> tileStoreSupplier; - @Inject public TileResource(Supplier<TileStore> tileStoreSupplier) { this.tileStoreSupplier = tileStoreSupplier; } - @GET - @javax.ws.rs.Path("/tiles/{z}/{x}/{y}.mvt") - public Response getTile(@PathParam("z") int z, @PathParam("x") int x, @PathParam("y") int y) { + @Get("regex:^/tiles/(?<z>[0-9]+)/(?<x>[0-9]+)/(?<y>[0-9]+).mvt$") + @Blocking + public HttpResponse tile(@Param("z") int z, @Param("x") int x, @Param("y") int y) { TileCoord tileCoord = new TileCoord(x, y, z); try { TileStore tileStore = tileStoreSupplier.get(); ByteBuffer blob = tileStore.read(tileCoord); if (blob != null) { + var headers = ResponseHeaders.builder(200) + .add(CONTENT_TYPE, TILE_TYPE) + .add(CONTENT_ENCODING, TILE_ENCODING) + .add(ACCESS_CONTROL_ALLOW_ORIGIN, "*") + .build(); byte[] bytes = new byte[blob.remaining()]; blob.get(bytes); - return Response.status(200) // lgtm [java/xss] - .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*") - .header(CONTENT_TYPE, TILE_TYPE) - .header(CONTENT_ENCODING, TILE_ENCODING) - .entity(bytes) - .build(); + HttpData data = HttpData.wrap(bytes); + return HttpResponse.of(headers, data); + } else { - return Response.status(204).build(); + return HttpResponse.of(204); } } catch (TileStoreException ex) { logger.error("Error while reading tile.", ex); - return Response.status(404).build(); + return HttpResponse.of(404); } } diff --git a/baremaps-server/src/main/java/org/apache/baremaps/server/TilesetResource.java b/baremaps-server/src/main/java/org/apache/baremaps/server/TilesetResource.java index d2434b84..eb317ad9 100644 --- a/baremaps-server/src/main/java/org/apache/baremaps/server/TilesetResource.java +++ b/baremaps-server/src/main/java/org/apache/baremaps/server/TilesetResource.java @@ -17,32 +17,25 @@ package org.apache.baremaps.server; +import com.linecorp.armeria.server.annotation.Get; +import com.linecorp.armeria.server.annotation.ProducesJson; import java.util.function.Supplier; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.ws.rs.GET; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; import org.apache.baremaps.vectortile.tileset.Tileset; /** * A resource that provides access to the tileset file. Only suitable for development purposes, as * it exposes SQL queries. */ -@Singleton [email protected]("/") public class TilesetResource { private final Supplier<Tileset> tilesetSupplier; - @Inject public TilesetResource(Supplier<Tileset> tilesetSupplier) { this.tilesetSupplier = tilesetSupplier; } - @GET - @javax.ws.rs.Path("tiles.json") - @Produces(MediaType.APPLICATION_JSON) + @Get("/tiles.json") + @ProducesJson public Tileset getTileset() { var tileset = tilesetSupplier.get(); // Hide the database connection diff --git a/pom.xml b/pom.xml index 54a75195..2aa0e735 100644 --- a/pom.xml +++ b/pom.xml @@ -80,6 +80,7 @@ limitations under the License. <sonar.organization>apache</sonar.organization> <sonar.projectKey>apache_baremaps</sonar.projectKey> <version.lib.annotation-api>1.3.2</version.lib.annotation-api> + <version.lib.armeria>1.26.4</version.lib.armeria> <version.lib.awaitability>4.2.0</version.lib.awaitability> <version.lib.awssdk>2.21.5</version.lib.awssdk> <version.lib.caffeine>3.1.8</version.lib.caffeine> @@ -180,6 +181,16 @@ limitations under the License. <artifactId>protobuf-java</artifactId> <version>${version.lib.protobuf}</version> </dependency> + <dependency> + <groupId>com.linecorp.armeria</groupId> + <artifactId>armeria</artifactId> + <version>${version.lib.armeria}</version> + </dependency> + <dependency> + <groupId>com.linecorp.armeria</groupId> + <artifactId>armeria-reactor3</artifactId> + <version>${version.lib.armeria}</version> + </dependency> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId>
