From 74132e4d11a13d6c3a72bd0acf6f1d89fde9af66 Mon Sep 17 00:00:00 2001 From: Mike Hearn Date: Mon, 7 Oct 2024 14:09:12 +0200 Subject: [PATCH] ReactJS: Add a lambda helper to BeanPool. --- .../views/react/ReactViewsRenderer.java | 13 +++++----- .../micronaut/views/react/util/BeanPool.java | 24 +++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/views-react/src/main/java/io/micronaut/views/react/ReactViewsRenderer.java b/views-react/src/main/java/io/micronaut/views/react/ReactViewsRenderer.java index 57c693543..19c38f3a3 100644 --- a/views-react/src/main/java/io/micronaut/views/react/ReactViewsRenderer.java +++ b/views-react/src/main/java/io/micronaut/views/react/ReactViewsRenderer.java @@ -62,15 +62,18 @@ class ReactViewsRenderer implements ViewsRenderer>, * or introspectable object), returns hydratable HTML that can be booted on the client using * the React libraries. * - * @param viewName The function or class name of the React component to use as the root. It should return an html root tag. + * @param viewName The function or class name of the React component to use as the root. It should return an HTML root tag. * @param props If non-null, will be exposed to the given component as React props. * @param request The HTTP request object. */ @Override public @NonNull Writable render(@NonNull String viewName, @Nullable PROPS props, @Nullable HttpRequest request) { return writer -> { - try (BeanPool.Handle contextHandle = beanPool.checkOut()) { - render(viewName, props, writer, contextHandle.get(), request); + try { + beanPool.useContext(handle -> { + render(viewName, props, writer, handle.get(), request); + return null; + }); } catch (BeanInstantiationException e) { throw e; } catch (Exception e) { @@ -82,9 +85,7 @@ class ReactViewsRenderer implements ViewsRenderer>, @Override public boolean exists(@NonNull String viewName) { - try (var contextHandle = beanPool.checkOut()) { - return contextHandle.get().moduleHasMember(viewName); - } + return beanPool.useContext(handle -> handle.get().moduleHasMember(viewName)); } private void render(String componentName, PROPS props, Writer writer, ReactJSContext context, @Nullable HttpRequest request) { diff --git a/views-react/src/main/java/io/micronaut/views/react/util/BeanPool.java b/views-react/src/main/java/io/micronaut/views/react/util/BeanPool.java index b1616cd23..55c5bcba0 100644 --- a/views-react/src/main/java/io/micronaut/views/react/util/BeanPool.java +++ b/views-react/src/main/java/io/micronaut/views/react/util/BeanPool.java @@ -16,6 +16,7 @@ package io.micronaut.views.react.util; import io.micronaut.core.annotation.Internal; +import io.micronaut.core.util.functional.ThrowingFunction; import java.io.Closeable; import java.io.IOException; @@ -115,6 +116,29 @@ public synchronized void checkIn(Handle handle) { } } + /** + * Runs the block with a handle checked out, checking it back in again at the end even if an + * exception is thrown. + * + *

+ * This is implemented equivalently to: + *

+     * try (Handle handle = checkOut()) {
+     *     return block.apply(handle);
+     * }
+     * 
+ * + * @param block The lambda that will be executed with the checked out handle. + * @param Return type of the block. + * @param What type of exception the block can throw. + * @return the same object returned by the block. + */ + public R useContext(ThrowingFunction, R, E> block) throws E { + try (Handle handle = checkOut()) { + return block.apply(handle); + } + } + /** * Empties the pool. Beans currently checked out with {@link #checkOut()} will not be re-added * to the pool when {@link #checkIn(Handle)} is called, and may be closed if they are