diff --git a/documentation/src/docs/asciidoc/user-guide/extensions.adoc b/documentation/src/docs/asciidoc/user-guide/extensions.adoc index 4d7c5020d6ad..67089303fe97 100644 --- a/documentation/src/docs/asciidoc/user-guide/extensions.adoc +++ b/documentation/src/docs/asciidoc/user-guide/extensions.adoc @@ -693,7 +693,6 @@ Please refer to the implementations of <> or <> which use this extension point to provide their functionality. - [[extensions-keeping-state]] === Keeping State in Extensions @@ -714,6 +713,26 @@ extension context lifecycle ends it closes its associated store. All stored valu that are instances of `CloseableResource` are notified by an invocation of their `close()` method in the inverse order they were added in. +An example use-case of `ClosableResource` is shown below, using an `HttpServer` resource. + +[source,java,indent=0] +.HttpServer resource implementing `ClosableResource` +---- +include::{testDir}/example/extensions/HttpServerResource.java[tags=user_guide] +---- + +This resource can then be stored in the desired `ExtensionContext`. +The resource can be stored at class- or method-level if needed, +but this may add unnecessary overhead for this type of resource. +For this example it might be prudent to store it at root level +and instantiate it lazily to ensure it's only created once per execution. + +[source,java,indent=0] +.Storing in root context with `Store.getOrComputeIfAbsent` +---- +include::{testDir}/example/extensions/HttpServerExtension.java[tags=user_guide] +---- + [[extensions-supported-utilities]] === Supported Utilities in Extensions diff --git a/documentation/src/test/java/example/extensions/HttpServerExtension.java b/documentation/src/test/java/example/extensions/HttpServerExtension.java new file mode 100644 index 000000000000..b2a6c334948a --- /dev/null +++ b/documentation/src/test/java/example/extensions/HttpServerExtension.java @@ -0,0 +1,37 @@ +/* + * Copyright 2015-2024 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package example.extensions; + +import java.io.IOException; + +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; + +// tag::user_guide[] +public class HttpServerExtension implements BeforeAllCallback { + @Override + public void beforeAll(ExtensionContext context) throws Exception { + HttpServerResource resource = context.getRoot().getStore(Namespace.GLOBAL).getOrComputeIfAbsent( + HttpServerResource.class.getName(), key -> { + try { + HttpServerResource serverResource = new HttpServerResource(8080); + serverResource.start(); + return serverResource; + } + catch (IOException e) { + throw new RuntimeException("Failed to create HttpServerResource", e); + } + }, HttpServerResource.class); + // Now you can use the resource within your tests + } +} +// end::user_guide[] diff --git a/documentation/src/test/java/example/extensions/HttpServerResource.java b/documentation/src/test/java/example/extensions/HttpServerResource.java new file mode 100644 index 000000000000..094dfbb3de15 --- /dev/null +++ b/documentation/src/test/java/example/extensions/HttpServerResource.java @@ -0,0 +1,64 @@ +/* + * Copyright 2015-2024 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package example.extensions; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; + +import com.sun.net.httpserver.HttpServer; + +import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource; + +/** + * Demonstrates an implementation of {@link CloseableResource} using an {@link HttpServer}. + */ +// tag::user_guide[] +public class HttpServerResource implements CloseableResource { + private final HttpServer httpServer; + + // end::user_guide[] + /** + * Initializes the Http server resource, using the given port. + * + * @param port (int) The port number for the server, must be in the range 0-65535. + * @throws IOException if an IOException occurs during initialization. + */ + // tag::user_guide[] + public HttpServerResource(int port) throws IOException { + this.httpServer = HttpServer.create(new InetSocketAddress(port), 0); + } + + // end::user_guide[] + + /** + * Starts the Http server with an example handler. + */ + // tag::user_guide[] + public void start() { + //Example handler + httpServer.createContext("/example", exchange -> { + String test = "This is a test."; + exchange.sendResponseHeaders(200, test.length()); + try (OutputStream os = exchange.getResponseBody()) { + os.write(test.getBytes()); + } + }); + httpServer.setExecutor(null); + httpServer.start(); + } + + @Override + public void close() throws Throwable { + httpServer.stop(0); + } +} +// end::user_guide[]