diff --git a/component-runtime-testing/component-runtime-junit/src/main/java/org/talend/sdk/component/junit/BaseComponentsHandler.java b/component-runtime-testing/component-runtime-junit/src/main/java/org/talend/sdk/component/junit/BaseComponentsHandler.java index dfa87a68b8b6a..5f2547cca3535 100644 --- a/component-runtime-testing/component-runtime-junit/src/main/java/org/talend/sdk/component/junit/BaseComponentsHandler.java +++ b/component-runtime-testing/component-runtime-junit/src/main/java/org/talend/sdk/component/junit/BaseComponentsHandler.java @@ -87,12 +87,10 @@ public class BaseComponentsHandler implements ComponentsHandler { protected static final Local STATE = loadStateHolder(); private static Local loadStateHolder() { - switch (System.getProperty("talend.component.junit.handler.state", "thread").toLowerCase(ROOT)) { - case "static": - return new Local.StaticImpl<>(); - default: - return new Local.ThreadLocalImpl<>(); - } + final String handlerState = System.getProperty("talend.component.junit.handler.state", "thread"); + return "static".equals(handlerState.toLowerCase(ROOT)) + ? new Local.StaticImpl<>() + : new Local.ThreadLocalImpl<>(); } private final ThreadLocal initState = ThreadLocal.withInitial(PreState::new); @@ -111,13 +109,14 @@ public T injectServices(final T instance) { .orElseThrow(() -> new IllegalArgumentException("cant find plugin '" + plugin + "'")) .get(ComponentManager.AllServices.class) .getServices(); - Injector.class.cast(services.get(Injector.class)).inject(instance); + ((Injector) services.get(Injector.class)).inject(instance); return instance; } public BaseComponentsHandler withIsolatedPackage(final String packageName, final String... packages) { - isolatedPackages = - Stream.concat(Stream.of(packageName), Stream.of(packages)).filter(Objects::nonNull).collect(toList()); + isolatedPackages = Stream.concat(Stream.of(packageName), Stream.of(packages)) + .filter(Objects::nonNull) + .collect(toList()); if (isolatedPackages.isEmpty()) { isolatedPackages = null; } @@ -140,14 +139,10 @@ protected boolean isContainerClass(final Filter filter, final String name) { public void close() { try { final State state = STATE.get(); - if (state.jsonb != null) { - try { - state.jsonb.close(); - } catch (final Exception e) { - // no-op: not important - } + if (state != null) { + state.cleanUp(); + STATE.remove(); } - STATE.remove(); initState.remove(); } finally { super.close(); @@ -170,7 +165,7 @@ public Outputs collect(final Processor processor, final ControllableInputFactory * Collects all outputs of a processor. * * @param processor the processor to run while there are inputs. - * @param inputs the input factory, when an input will return null it will stop the + * @param inputs The input factory, when an input returns null, it will stop the * processing. * @param bundleSize the bundle size to use. * @return a map where the key is the output name and the value a stream of the @@ -203,10 +198,10 @@ public Stream collect(final Class recordType, final Mapper mapper, fin /** * Collects data emitted from this mapper. If the split creates more than one - * mapper, it will create as much threads as mappers otherwise it will use the + * mapper, it will create as many threads as mappers, otherwise it will use the * caller thread. * - * IMPORTANT: don't forget to consume all the stream to ensure the underlying + * IMPORTANT: don't forget to consume the stream entirely to ensure the underlying * { @see org.talend.sdk.component.runtime.input.Input} is closed. * * @param recordType the record type to use to type the returned type. @@ -268,7 +263,7 @@ public Stream collect(final Class recordType, final Mapper mapper, fin latch.countDown(); } })) - .collect(toList()); + .toList(); es.shutdown(); final int timeout = Integer.getInteger("talend.component.junit.timeout", 5); @@ -601,6 +596,16 @@ synchronized RecordBuilderFactory recordBuilderFactory() { } return recordBuilderFactory; } + + synchronized void cleanUp() { + if (jsonb != null) { + try { + jsonb.close(); + } catch (final Exception e) { + // no-op: not important + } + } + } } public static class EmbeddedComponentManager extends ComponentManager { @@ -653,7 +658,7 @@ public List get(final Class type, final String name) { } } - interface Local { + protected interface Local { void set(T value); diff --git a/component-runtime-testing/component-runtime-junit/src/main/java/org/talend/sdk/component/junit5/ComponentExtension.java b/component-runtime-testing/component-runtime-junit/src/main/java/org/talend/sdk/component/junit5/ComponentExtension.java index 1fb2bae9656ad..d99f5de90b08b 100644 --- a/component-runtime-testing/component-runtime-junit/src/main/java/org/talend/sdk/component/junit5/ComponentExtension.java +++ b/component-runtime-testing/component-runtime-junit/src/main/java/org/talend/sdk/component/junit5/ComponentExtension.java @@ -33,7 +33,7 @@ /** * Extension allowing the test to use a {@link org.talend.sdk.component.junit.ComponentsHandler} - * and auto register components from current project. + * and auto register components from the current project. */ public class ComponentExtension extends BaseComponentsHandler implements BeforeAllCallback, AfterAllCallback, JUnit5InjectionSupport, BeforeEachCallback, AfterEachCallback { diff --git a/component-runtime-testing/component-runtime-junit/src/test/java/org/talend/sdk/component/junit/BaseComponentHandlerTest.java b/component-runtime-testing/component-runtime-junit/src/test/java/org/talend/sdk/component/junit/BaseComponentHandlerTest.java new file mode 100644 index 0000000000000..0d9f415e3ef99 --- /dev/null +++ b/component-runtime-testing/component-runtime-junit/src/test/java/org/talend/sdk/component/junit/BaseComponentHandlerTest.java @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2006-2026 Talend Inc. - www.talend.com + * + * 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 + * + * http://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 org.talend.sdk.component.junit; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import org.junit.jupiter.api.Test; + +class BaseComponentHandlerTest { + + @Test + void canCloseTheEmbeddedManagerTwice() { + final MyBaseComponentsHandler myBaseComponentsHandler = new MyBaseComponentsHandler("org.talend.sdk.component.junit"); + final BaseComponentsHandler.EmbeddedComponentManager start = myBaseComponentsHandler.start(); + try { + assertNotNull(BaseComponentsHandler.STATE.get()); + start.close(); + assertNull(BaseComponentsHandler.STATE.get()); + start.close(); + assertNull(BaseComponentsHandler.STATE.get()); + } finally { + start.close(); + } + } + + private static class MyBaseComponentsHandler extends BaseComponentsHandler { + public MyBaseComponentsHandler(final String packageName) { + this.packageName = packageName; + } + } + +} diff --git a/pom.xml b/pom.xml index 82180eb5d2248..244ba2ac3a199 100644 --- a/pom.xml +++ b/pom.xml @@ -204,7 +204,7 @@ 1.0.12 1.0.3 1.2.2 - 5.10.0 + 5.14.3 4.8.1 1.3 2.16.0