diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/AutoCloseBeanTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/AutoCloseBeanTest.java new file mode 100644 index 000000000..ec6daabcd --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/AutoCloseBeanTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.bean; + +import static org.jboss.cdi.tck.cdi.Sections.AUTO_CLOSING; +import static org.jboss.cdi.tck.cdi.Sections.BEAN; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.enterprise.inject.spi.Bean; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "5.0") +public class AutoCloseBeanTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(AutoCloseBeanTest.class) + .build(); + } + + @Test + @SpecAssertion(section = AUTO_CLOSING, id = "aa") + @SpecAssertion(section = AUTO_CLOSING, id = "b") + public void testAutoClose() { + Bean bean = getUniqueBean(WithAutoCloseBean.class); + CreationalContext cc = getCurrentBeanContainer().createCreationalContext(bean); + WithAutoCloseBean instance = bean.create(cc); + assertFalse(instance.closed); + bean.destroy(instance, cc); + assertTrue(instance.destroyed); + assertTrue(instance.closed); + } + + @Test + @SpecAssertion(section = AUTO_CLOSING, id = "aa") + @SpecAssertion(section = AUTO_CLOSING, id = "b") + public void testNoAutoClose() { + Bean bean = getUniqueBean(WithoutAutoCloseBean.class); + CreationalContext cc = getCurrentBeanContainer().createCreationalContext(bean); + WithoutAutoCloseBean instance = bean.create(cc); + bean.destroy(instance, cc); + assertTrue(instance.destroyed); + } + + @Test + @SpecAssertion(section = BEAN, id = "bg") + public void testMetadata() { + assertTrue(getUniqueBean(WithAutoCloseBean.class).isAutoClose()); + assertTrue(getUniqueBean(WithoutAutoCloseBean.class).isAutoClose()); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/WithAutoCloseBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/WithAutoCloseBean.java new file mode 100644 index 000000000..87cb93231 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/WithAutoCloseBean.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.bean; + +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; + +@Dependent +@AutoClose +public class WithAutoCloseBean implements AutoCloseable { + public boolean destroyed = false; + public boolean closed = false; + + @PreDestroy + public void destroy() { + destroyed = true; + } + + @Override + public void close() throws Exception { + closed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/WithoutAutoCloseBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/WithoutAutoCloseBean.java new file mode 100644 index 000000000..416d363ea --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/WithoutAutoCloseBean.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.bean; + +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; + +@Dependent +@AutoClose +public class WithoutAutoCloseBean { + public boolean destroyed = false; + + @PreDestroy + public void destroy() { + destroyed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/dependent/AutoCloseDependentBeanTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/dependent/AutoCloseDependentBeanTest.java new file mode 100644 index 000000000..7f4d54637 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/dependent/AutoCloseDependentBeanTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.bean.dependent; + +import static org.jboss.cdi.tck.cdi.Sections.AUTO_CLOSING; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import jakarta.enterprise.inject.Instance; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "5.0") +public class AutoCloseDependentBeanTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(AutoCloseDependentBeanTest.class) + .build(); + } + + @Test + @SpecAssertion(section = AUTO_CLOSING, id = "aa") + @SpecAssertion(section = AUTO_CLOSING, id = "b") + public void test() { + Instance instance = getCurrentBeanContainer().createInstance(); + ConsumerBean bean = instance.select(ConsumerBean.class).get(); + + assertFalse(DependentBean.closed); + instance.destroy(bean); + assertTrue(DependentBean.closed); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/dependent/ConsumerBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/dependent/ConsumerBean.java new file mode 100644 index 000000000..a6cdf6ccf --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/dependent/ConsumerBean.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.bean.dependent; + +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; + +@Dependent +public class ConsumerBean { + @Inject + DependentBean bean; +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/dependent/DependentBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/dependent/DependentBean.java new file mode 100644 index 000000000..76bb342d4 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/bean/dependent/DependentBean.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.bean.dependent; + +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; + +@Dependent +@AutoClose +public class DependentBean implements AutoCloseable { + public static boolean closed = false; + + @Override + public void close() throws Exception { + closed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/AutoCloseProducerFieldTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/AutoCloseProducerFieldTest.java new file mode 100644 index 000000000..bb5fd361c --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/AutoCloseProducerFieldTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.field; + +import static org.jboss.cdi.tck.cdi.Sections.AUTO_CLOSING; +import static org.jboss.cdi.tck.cdi.Sections.BEAN; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.enterprise.inject.spi.Bean; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "5.0") +public class AutoCloseProducerFieldTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(AutoCloseProducerFieldTest.class) + .build(); + } + + @Test + @SpecAssertion(section = AUTO_CLOSING, id = "ac") + @SpecAssertion(section = AUTO_CLOSING, id = "b") + public void testWithAutoClose() { + Bean bean = getUniqueBean(WithAutoClose.class); + CreationalContext cc = getCurrentBeanContainer().createCreationalContext(bean); + WithAutoClose instance = bean.create(cc); + assertFalse(Producers.withAutoCloseDisposed); + assertFalse(instance.closed); + bean.destroy(instance, cc); + assertTrue(Producers.withAutoCloseDisposed); + assertTrue(instance.closed); + } + + @Test + @SpecAssertion(section = AUTO_CLOSING, id = "ac") + @SpecAssertion(section = AUTO_CLOSING, id = "b") + public void testWithoutAutoClose() { + Bean bean = getUniqueBean(WithoutAutoClose.class); + CreationalContext cc = getCurrentBeanContainer().createCreationalContext(bean); + WithoutAutoClose instance = bean.create(cc); + assertFalse(Producers.withoutAutoCloseDisposed); + bean.destroy(instance, cc); + assertTrue(Producers.withoutAutoCloseDisposed); + } + + @Test + @SpecAssertion(section = BEAN, id = "bg") + public void testMetadata() { + assertTrue(getUniqueBean(WithAutoClose.class).isAutoClose()); + assertTrue(getUniqueBean(WithoutAutoClose.class).isAutoClose()); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/Producers.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/Producers.java new file mode 100644 index 000000000..4f493a7f6 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/Producers.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.field; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Disposes; +import jakarta.enterprise.inject.Produces; + +@ApplicationScoped +public class Producers { + static boolean withAutoCloseDisposed = false; + static boolean withoutAutoCloseDisposed = false; + + @Produces + @Dependent + @AutoClose + WithAutoClose withAutoClose = new WithAutoClose(); + + @Produces + @Dependent + @AutoClose + WithoutAutoClose withoutAutoClose = new WithoutAutoClose(); + + public void disposeWithAutoClose(@Disposes WithAutoClose withAutoClose) { + withAutoCloseDisposed = true; + } + + public void disposeWithoutAutoClose(@Disposes WithoutAutoClose withAutoClose) { + withoutAutoCloseDisposed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/WithAutoClose.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/WithAutoClose.java new file mode 100644 index 000000000..077a5f3d3 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/WithAutoClose.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.field; + +public class WithAutoClose implements AutoCloseable { + public boolean closed = false; + + @Override + public void close() throws Exception { + closed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/WithoutAutoClose.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/WithoutAutoClose.java new file mode 100644 index 000000000..095bd0647 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/WithoutAutoClose.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.field; + +public class WithoutAutoClose { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/dependent/AutoCloseDependentProducerFieldTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/dependent/AutoCloseDependentProducerFieldTest.java new file mode 100644 index 000000000..1ed466c25 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/dependent/AutoCloseDependentProducerFieldTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.field.dependent; + +import static org.jboss.cdi.tck.cdi.Sections.AUTO_CLOSING; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import jakarta.enterprise.inject.Instance; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "5.0") +public class AutoCloseDependentProducerFieldTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(AutoCloseDependentProducerFieldTest.class) + .build(); + } + + @Test + @SpecAssertion(section = AUTO_CLOSING, id = "ac") + @SpecAssertion(section = AUTO_CLOSING, id = "b") + public void test() { + Instance instance = getCurrentBeanContainer().createInstance(); + ConsumerBean bean = instance.select(ConsumerBean.class).get(); + + assertFalse(DependentBean.closed); + instance.destroy(bean); + assertTrue(DependentBean.closed); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/dependent/ConsumerBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/dependent/ConsumerBean.java new file mode 100644 index 000000000..1b8d48f6b --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/dependent/ConsumerBean.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.field.dependent; + +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; + +@Dependent +public class ConsumerBean { + @Inject + DependentBean bean; +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/dependent/DependentBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/dependent/DependentBean.java new file mode 100644 index 000000000..9c6bec376 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/dependent/DependentBean.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.field.dependent; + +public class DependentBean implements AutoCloseable { + public static boolean closed = false; + + @Override + public void close() throws Exception { + closed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/dependent/DependentBeanProducer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/dependent/DependentBeanProducer.java new file mode 100644 index 000000000..32146aade --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/field/dependent/DependentBeanProducer.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.field.dependent; + +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Produces; + +@Dependent +public class DependentBeanProducer { + @Produces + @Dependent + @AutoClose + public DependentBean produce = new DependentBean(); +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/AutoCloseProducerMethodTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/AutoCloseProducerMethodTest.java new file mode 100644 index 000000000..b52deac58 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/AutoCloseProducerMethodTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.method; + +import static org.jboss.cdi.tck.cdi.Sections.AUTO_CLOSING; +import static org.jboss.cdi.tck.cdi.Sections.BEAN; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.enterprise.inject.spi.Bean; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "5.0") +public class AutoCloseProducerMethodTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(AutoCloseProducerMethodTest.class) + .build(); + } + + @Test + @SpecAssertion(section = AUTO_CLOSING, id = "ab") + @SpecAssertion(section = AUTO_CLOSING, id = "b") + public void testWithAutoClose() { + Bean bean = getUniqueBean(WithAutoClose.class); + CreationalContext cc = getCurrentBeanContainer().createCreationalContext(bean); + WithAutoClose instance = bean.create(cc); + assertFalse(Producers.withAutoCloseDisposed); + assertFalse(instance.closed); + bean.destroy(instance, cc); + assertTrue(Producers.withAutoCloseDisposed); + assertTrue(instance.closed); + } + + @Test + @SpecAssertion(section = AUTO_CLOSING, id = "ab") + @SpecAssertion(section = AUTO_CLOSING, id = "b") + public void testWithoutAutoClose() { + Bean bean = getUniqueBean(WithoutAutoClose.class); + CreationalContext cc = getCurrentBeanContainer().createCreationalContext(bean); + WithoutAutoClose instance = bean.create(cc); + assertFalse(Producers.withoutAutoCloseDisposed); + bean.destroy(instance, cc); + assertTrue(Producers.withoutAutoCloseDisposed); + } + + @Test + @SpecAssertion(section = BEAN, id = "bg") + public void testMetadata() { + assertTrue(getUniqueBean(WithAutoClose.class).isAutoClose()); + assertTrue(getUniqueBean(WithoutAutoClose.class).isAutoClose()); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/Producers.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/Producers.java new file mode 100644 index 000000000..ec513aaf9 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/Producers.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.method; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Disposes; +import jakarta.enterprise.inject.Produces; + +@ApplicationScoped +public class Producers { + static boolean withAutoCloseDisposed = false; + static boolean withoutAutoCloseDisposed = false; + + @Produces + @Dependent + @AutoClose + public WithAutoClose withAutoClose() { + return new WithAutoClose(); + } + + @Produces + @Dependent + @AutoClose + public WithoutAutoClose withoutAutoClose() { + return new WithoutAutoClose(); + } + + public void disposeWithAutoClose(@Disposes WithAutoClose withAutoClose) { + withAutoCloseDisposed = true; + } + + public void disposeWithoutAutoClose(@Disposes WithoutAutoClose withAutoClose) { + withoutAutoCloseDisposed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/WithAutoClose.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/WithAutoClose.java new file mode 100644 index 000000000..d0bfad732 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/WithAutoClose.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.method; + +public class WithAutoClose implements AutoCloseable { + public boolean closed = false; + + @Override + public void close() throws Exception { + closed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/WithoutAutoClose.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/WithoutAutoClose.java new file mode 100644 index 000000000..3be8e0bec --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/WithoutAutoClose.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.method; + +public class WithoutAutoClose { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/dependent/AutoCloseDependentProducerMethodTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/dependent/AutoCloseDependentProducerMethodTest.java new file mode 100644 index 000000000..78b32a66b --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/dependent/AutoCloseDependentProducerMethodTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.method.dependent; + +import static org.jboss.cdi.tck.cdi.Sections.AUTO_CLOSING; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import jakarta.enterprise.inject.Instance; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "5.0") +public class AutoCloseDependentProducerMethodTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(AutoCloseDependentProducerMethodTest.class) + .build(); + } + + @Test + @SpecAssertion(section = AUTO_CLOSING, id = "ab") + @SpecAssertion(section = AUTO_CLOSING, id = "b") + public void test() { + Instance instance = getCurrentBeanContainer().createInstance(); + ConsumerBean bean = instance.select(ConsumerBean.class).get(); + + assertFalse(DependentBean.closed); + instance.destroy(bean); + assertTrue(DependentBean.closed); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/dependent/ConsumerBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/dependent/ConsumerBean.java new file mode 100644 index 000000000..eb2945d42 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/dependent/ConsumerBean.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.method.dependent; + +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; + +@Dependent +public class ConsumerBean { + @Inject + DependentBean bean; +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/dependent/DependentBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/dependent/DependentBean.java new file mode 100644 index 000000000..d4606b5a1 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/dependent/DependentBean.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.method.dependent; + +public class DependentBean implements AutoCloseable { + public static boolean closed = false; + + @Override + public void close() throws Exception { + closed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/dependent/DependentBeanProducer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/dependent/DependentBeanProducer.java new file mode 100644 index 000000000..61897078b --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/producer/method/dependent/DependentBeanProducer.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.producer.method.dependent; + +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Produces; + +@Dependent +public class DependentBeanProducer { + @Produces + @Dependent + @AutoClose + public DependentBean produce() { + return new DependentBean(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/stereotype/AutoCloseStereotype.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/stereotype/AutoCloseStereotype.java new file mode 100644 index 000000000..289fe4088 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/stereotype/AutoCloseStereotype.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.stereotype; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Stereotype; + +@Stereotype +@AutoClose +@Dependent +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface AutoCloseStereotype { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/stereotype/AutoCloseStereotypeBeanTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/stereotype/AutoCloseStereotypeBeanTest.java new file mode 100644 index 000000000..cbe54e51d --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/stereotype/AutoCloseStereotypeBeanTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.stereotype; + +import static org.jboss.cdi.tck.cdi.Sections.AUTO_CLOSE_STEREOTYPE; +import static org.jboss.cdi.tck.cdi.Sections.BEAN; +import static org.jboss.cdi.tck.cdi.Sections.STEREOTYPES; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.enterprise.inject.spi.Bean; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "5.0") +public class AutoCloseStereotypeBeanTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(AutoCloseStereotypeBeanTest.class) + .build(); + } + + @Test + @SpecAssertion(section = STEREOTYPES, id = "af") + @SpecAssertion(section = AUTO_CLOSE_STEREOTYPE, id = "a") + public void testWithAutoClose() { + Bean bean = getUniqueBean(WithAutoCloseBean.class); + CreationalContext cc = getCurrentBeanContainer().createCreationalContext(bean); + WithAutoCloseBean instance = bean.create(cc); + assertFalse(instance.closed); + assertFalse(instance.destroyed); + bean.destroy(instance, cc); + assertTrue(instance.destroyed); + assertTrue(instance.closed); + } + + @Test + @SpecAssertion(section = STEREOTYPES, id = "af") + @SpecAssertion(section = AUTO_CLOSE_STEREOTYPE, id = "a") + public void testWithoutAutoClose() { + Bean bean = getUniqueBean(WithoutAutoCloseBean.class); + CreationalContext cc = getCurrentBeanContainer().createCreationalContext(bean); + WithoutAutoCloseBean instance = bean.create(cc); + assertFalse(instance.destroyed); + bean.destroy(instance, cc); + assertTrue(instance.destroyed); + } + + @Test + @SpecAssertion(section = BEAN, id = "bg") + public void testMetadata() { + assertTrue(getUniqueBean(WithAutoCloseBean.class).isAutoClose()); + assertTrue(getUniqueBean(WithoutAutoCloseBean.class).isAutoClose()); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/stereotype/WithAutoCloseBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/stereotype/WithAutoCloseBean.java new file mode 100644 index 000000000..c527c8205 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/stereotype/WithAutoCloseBean.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.stereotype; + +import jakarta.annotation.PreDestroy; + +@AutoCloseStereotype +public class WithAutoCloseBean implements AutoCloseable { + public boolean destroyed = false; + public boolean closed = false; + + @PreDestroy + public void destroy() { + destroyed = true; + } + + @Override + public void close() throws Exception { + closed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/stereotype/WithoutAutoCloseBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/stereotype/WithoutAutoCloseBean.java new file mode 100644 index 000000000..a82043567 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/stereotype/WithoutAutoCloseBean.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.stereotype; + +import jakarta.annotation.PreDestroy; + +@AutoCloseStereotype +public class WithoutAutoCloseBean { + public boolean destroyed = false; + + @PreDestroy + public void destroy() { + destroyed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/AutoCloseSyntheticBeanTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/AutoCloseSyntheticBeanTest.java new file mode 100644 index 000000000..cc9ade9a0 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/AutoCloseSyntheticBeanTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean; + +import static org.jboss.cdi.tck.cdi.Sections.AUTO_CLOSING; +import static org.jboss.cdi.tck.cdi.Sections.BEAN; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.enterprise.inject.spi.Bean; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "5.0") +public class AutoCloseSyntheticBeanTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(AutoCloseSyntheticBeanTest.class) + .withBuildCompatibleExtension(SyntheticBeanExtension.class) + .build(); + } + + @Test + @SpecAssertion(section = AUTO_CLOSING, id = "ad") + @SpecAssertion(section = AUTO_CLOSING, id = "b") + public void testWithAutoClose() { + Bean bean = getUniqueBean(WithAutoClose.class); + CreationalContext cc = getCurrentBeanContainer().createCreationalContext(bean); + WithAutoClose instance = bean.create(cc); + assertFalse(WithAutoCloseDisposer.disposed); + assertFalse(instance.closed); + bean.destroy(instance, cc); + assertTrue(WithAutoCloseDisposer.disposed); + assertTrue(instance.closed); + } + + @Test + @SpecAssertion(section = AUTO_CLOSING, id = "ad") + @SpecAssertion(section = AUTO_CLOSING, id = "b") + public void testWithoutAutoClose() { + Bean bean = getUniqueBean(WithoutAutoClose.class); + CreationalContext cc = getCurrentBeanContainer().createCreationalContext(bean); + WithoutAutoClose instance = bean.create(cc); + assertFalse(WithoutAutoCloseDisposer.disposed); + bean.destroy(instance, cc); + assertTrue(WithoutAutoCloseDisposer.disposed); + } + + @Test + @SpecAssertion(section = BEAN, id = "bf") + public void testMetadata() { + assertTrue(getUniqueBean(WithAutoClose.class).isAutoClose()); + assertTrue(getUniqueBean(WithoutAutoClose.class).isAutoClose()); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/SyntheticBeanExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/SyntheticBeanExtension.java new file mode 100644 index 000000000..433408469 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/SyntheticBeanExtension.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean; + +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; + +public class SyntheticBeanExtension implements BuildCompatibleExtension { + @Synthesis + public void synthesize(SyntheticComponents syn) { + syn.addBean(WithAutoClose.class) + .type(WithAutoClose.class) + .scope(Dependent.class) + .autoClose(true) + .createWith(WithAutoCloseCreator.class) + .disposeWith(WithAutoCloseDisposer.class); + + syn.addBean(WithoutAutoClose.class) + .type(WithoutAutoClose.class) + .scope(Dependent.class) + .autoClose(true) + .createWith(WithoutAutoCloseCreator.class) + .disposeWith(WithoutAutoCloseDisposer.class); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithAutoClose.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithAutoClose.java new file mode 100644 index 000000000..59162ef67 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithAutoClose.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean; + +public class WithAutoClose implements AutoCloseable { + public boolean closed = false; + + @Override + public void close() throws Exception { + closed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithAutoCloseCreator.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithAutoCloseCreator.java new file mode 100644 index 000000000..a6c1c4495 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithAutoCloseCreator.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean; + +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanCreator; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticInjections; + +public class WithAutoCloseCreator implements SyntheticBeanCreator { + @Override + public WithAutoClose create(SyntheticInjections lookup, Parameters params) { + return new WithAutoClose(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithAutoCloseDisposer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithAutoCloseDisposer.java new file mode 100644 index 000000000..4cd01b4e4 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithAutoCloseDisposer.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean; + +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanDisposer; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticInjections; + +public class WithAutoCloseDisposer implements SyntheticBeanDisposer { + static boolean disposed = false; + + @Override + public void dispose(WithAutoClose instance, SyntheticInjections injections, Parameters params) { + disposed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithoutAutoClose.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithoutAutoClose.java new file mode 100644 index 000000000..88f582caa --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithoutAutoClose.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean; + +public class WithoutAutoClose { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithoutAutoCloseCreator.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithoutAutoCloseCreator.java new file mode 100644 index 000000000..d5111be0c --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithoutAutoCloseCreator.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean; + +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanCreator; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticInjections; + +public class WithoutAutoCloseCreator implements SyntheticBeanCreator { + @Override + public WithoutAutoClose create(SyntheticInjections lookup, Parameters params) { + return new WithoutAutoClose(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithoutAutoCloseDisposer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithoutAutoCloseDisposer.java new file mode 100644 index 000000000..aaaa6988a --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/WithoutAutoCloseDisposer.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean; + +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanDisposer; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticInjections; + +public class WithoutAutoCloseDisposer implements SyntheticBeanDisposer { + static boolean disposed = false; + + @Override + public void dispose(WithoutAutoClose instance, SyntheticInjections injections, Parameters params) { + disposed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/AutoCloseDependentSyntheticBeanTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/AutoCloseDependentSyntheticBeanTest.java new file mode 100644 index 000000000..e4bbe3a6b --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/AutoCloseDependentSyntheticBeanTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean.dependent; + +import static org.jboss.cdi.tck.cdi.Sections.AUTO_CLOSING; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import jakarta.enterprise.inject.Instance; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "5.0") +public class AutoCloseDependentSyntheticBeanTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(AutoCloseDependentSyntheticBeanTest.class) + .withBuildCompatibleExtension(SyntheticBeanExtension.class) + .build(); + } + + @Test + @SpecAssertion(section = AUTO_CLOSING, id = "ad") + @SpecAssertion(section = AUTO_CLOSING, id = "b") + public void test() { + Instance instance = getCurrentBeanContainer().createInstance(); + ConsumerBean bean = instance.select(ConsumerBean.class).get(); + + assertFalse(DependentBean.closed); + instance.destroy(bean); + assertTrue(DependentBean.closed); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/ConsumerBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/ConsumerBean.java new file mode 100644 index 000000000..37a562c9b --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/ConsumerBean.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean.dependent; + +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; + +@Dependent +public class ConsumerBean { + @Inject + DependentBean bean; +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/DependentBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/DependentBean.java new file mode 100644 index 000000000..aecf6b4d5 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/DependentBean.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean.dependent; + +public class DependentBean implements AutoCloseable { + public static boolean closed = false; + + @Override + public void close() throws Exception { + closed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/DependentBeanCreator.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/DependentBeanCreator.java new file mode 100644 index 000000000..cb0a1779c --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/DependentBeanCreator.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean.dependent; + +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanCreator; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticInjections; + +public class DependentBeanCreator implements SyntheticBeanCreator { + @Override + public DependentBean create(SyntheticInjections injections, Parameters params) { + return new DependentBean(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/SyntheticBeanExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/SyntheticBeanExtension.java new file mode 100644 index 000000000..36f61b681 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/autoclose/synthetic/bean/dependent/SyntheticBeanExtension.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.autoclose.synthetic.bean.dependent; + +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; + +public class SyntheticBeanExtension implements BuildCompatibleExtension { + @Synthesis + public void synthesize(SyntheticComponents syn) { + syn.addBean(DependentBean.class) + .type(DependentBean.class) + .scope(Dependent.class) + .autoClose(true) + .createWith(DependentBeanCreator.class); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/Barking.java b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/Barking.java new file mode 100644 index 000000000..593f255b0 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/Barking.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.full.extensions.producer; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.enterprise.util.AnnotationLiteral; +import jakarta.inject.Qualifier; + +@Target({ TYPE, METHOD, PARAMETER, FIELD }) +@Retention(RUNTIME) +@Documented +@Qualifier +public @interface Barking { + class Literal extends AnnotationLiteral implements Barking { + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/BarkingDog.java b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/BarkingDog.java new file mode 100644 index 000000000..2c1e6c8bf --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/BarkingDog.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.full.extensions.producer; + +public class BarkingDog extends VocalDog { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/CatCloseable.java b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/CatCloseable.java new file mode 100644 index 000000000..7aa09da5a --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/CatCloseable.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.full.extensions.producer; + +import jakarta.enterprise.context.AutoClose; + +@AutoClose +public class CatCloseable implements AutoCloseable { + static boolean closed = false; + + @Override + public void close() throws Exception { + closed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/DogProducer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/DogProducer.java index 24394d994..b98b29450 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/DogProducer.java +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/DogProducer.java @@ -13,6 +13,7 @@ */ package org.jboss.cdi.tck.tests.full.extensions.producer; +import jakarta.enterprise.context.AutoClose; import jakarta.enterprise.inject.Disposes; import jakarta.enterprise.inject.Produces; @@ -21,6 +22,8 @@ public class DogProducer { public static final String NOISY_DOG_COLOR = "White"; private static boolean noisyDogProducerCalled; private static boolean noisyDogDisposerCalled; + private static boolean barkingDogDisposerCalled; + private static boolean howlingDogDisposerCalled; @Produces @Quiet @@ -33,10 +36,31 @@ public Dog produceNoisyDog(DogBed dogBed) { return new Dog(NOISY_DOG_COLOR); } + @Produces + @Barking + @AutoClose + public VocalDog produceBarkingDog = new BarkingDog(); + + @Produces + @Howling + @AutoClose + public VocalDog produceHowlingDog() { + return new HowlingDog(); + } + public void disposeNoisyDog(@Disposes @Noisy Dog dog) { noisyDogDisposerCalled = true; } + public void disposeBarkingDog(@Disposes @Barking VocalDog dog) { + barkingDogDisposerCalled = true; + } + + public void disposeHowlingDog(@Disposes @Howling VocalDog dog) { + assert !HowlingDog.closed; + howlingDogDisposerCalled = true; + } + public static boolean isNoisyDogProducerCalled() { return noisyDogProducerCalled; } @@ -45,8 +69,18 @@ public static boolean isNoisyDogDisposerCalled() { return noisyDogDisposerCalled; } + public static boolean isBarkingDogDisposerCalled() { + return barkingDogDisposerCalled; + } + + public static boolean isHowlingDogDisposerCalled() { + return howlingDogDisposerCalled; + } + public static void reset() { DogProducer.noisyDogProducerCalled = false; DogProducer.noisyDogDisposerCalled = false; + DogProducer.barkingDogDisposerCalled = false; + DogProducer.howlingDogDisposerCalled = false; } } diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/Howling.java b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/Howling.java new file mode 100644 index 000000000..94a496d92 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/Howling.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.full.extensions.producer; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.enterprise.util.AnnotationLiteral; +import jakarta.inject.Qualifier; + +@Target({ TYPE, METHOD, PARAMETER, FIELD }) +@Retention(RUNTIME) +@Documented +@Qualifier +public @interface Howling { + class Literal extends AnnotationLiteral implements Howling { + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/HowlingDog.java b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/HowlingDog.java new file mode 100644 index 000000000..0281172cd --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/HowlingDog.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.full.extensions.producer; + +public class HowlingDog extends VocalDog implements AutoCloseable { + static boolean closed = false; + + @Override + public void close() throws Exception { + closed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/ProducerProcessor.java b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/ProducerProcessor.java index 47f0cba62..bcee99b8f 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/ProducerProcessor.java +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/ProducerProcessor.java @@ -30,8 +30,11 @@ public class ProducerProcessor implements Extension { private static InjectionTarget catInjectionTarget; + private static InjectionTarget catCloseableInjectionTarget; private static Producer noisyDogProducer; private static Producer quietDogProducer; + private static Producer barkingDogProducer; + private static Producer howlingDogProducer; private static InjectionTarget dogInjectionTarget; private static AnnotatedType dogAnnotatedType; private static boolean overriddenCowProducerCalled; @@ -54,10 +57,24 @@ public void processDogProducerProducer(@Observes ProcessProducer producerEvent) { + if (producerEvent.getAnnotatedMember().isAnnotationPresent(Barking.class)) { + barkingDogProducer = producerEvent.getProducer(); + assert producerEvent.getAnnotatedMember() instanceof AnnotatedField; + } else if (producerEvent.getAnnotatedMember().isAnnotationPresent(Howling.class)) { + howlingDogProducer = producerEvent.getProducer(); + assert producerEvent.getAnnotatedMember() instanceof AnnotatedMethod; + } + } + public void processCatProducer(@Observes ProcessInjectionTarget event) { catInjectionTarget = event.getInjectionTarget(); } + public void processCatCloseableProducer(@Observes ProcessInjectionTarget event) { + catCloseableInjectionTarget = event.getInjectionTarget(); + } + public void processDogInjectionTarget(@Observes ProcessInjectionTarget injectionTargetEvent) { // There a couple, but it does not matter which one is used for the tests dogInjectionTarget = injectionTargetEvent.getInjectionTarget(); @@ -95,10 +112,22 @@ public static Producer getQuietDogProducer() { return quietDogProducer; } + public static Producer getBarkingDogProducer() { + return barkingDogProducer; + } + + public static Producer getHowlingDogProducer() { + return howlingDogProducer; + } + public static InjectionTarget getCatInjectionTarget() { return catInjectionTarget; } + public static InjectionTarget getCatCloseableInjectionTarget() { + return catCloseableInjectionTarget; + } + public static InjectionTarget getDogInjectionTarget() { return dogInjectionTarget; } diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/ProducerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/ProducerTest.java index 8502165f7..c9cdd021c 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/ProducerTest.java +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/ProducerTest.java @@ -98,6 +98,18 @@ public void testDisposeDoesNothing() { cat.ping(); } + @Test + @SpecAssertions({ @SpecAssertion(section = INJECTIONTARGET, id = "c") }) + public void testDisposeCallsClose() { + InjectionTarget injectionTarget = ProducerProcessor.getCatCloseableInjectionTarget(); + + CatCloseable cat = getContextualReference(CatCloseable.class); + assert !CatCloseable.closed; + + injectionTarget.dispose(cat); + assert CatCloseable.closed; + } + @Test @SpecAssertions({ @SpecAssertion(section = INJECTIONTARGET, id = "da") }) public void testGetInjectionPointsForFields() { @@ -181,6 +193,32 @@ public void testProducerForMethodDisposesProduct() { assert DogProducer.isNoisyDogDisposerCalled(); } + @Test + @SpecAssertions({ @SpecAssertion(section = INJECTIONTARGET, id = "faa") }) + public void testProducerForMethodDisposesProductAndDoesntCallClose() { + Bean dogBean = getUniqueBean(VocalDog.class, new Barking.Literal()); + Producer producer = ProducerProcessor.getBarkingDogProducer(); + DogProducer.reset(); + VocalDog dog = producer.produce(getCurrentManager().createCreationalContext(dogBean)); + assert !DogProducer.isBarkingDogDisposerCalled(); + producer.dispose(dog); + assert DogProducer.isBarkingDogDisposerCalled(); + } + + @Test + @SpecAssertions({ @SpecAssertion(section = INJECTIONTARGET, id = "faa") }) + public void testProducerForMethodDisposesProductAndCallsClose() { + Bean dogBean = getUniqueBean(VocalDog.class, new Howling.Literal()); + Producer producer = ProducerProcessor.getHowlingDogProducer(); + DogProducer.reset(); + VocalDog dog = producer.produce(getCurrentManager().createCreationalContext(dogBean)); + assert !DogProducer.isHowlingDogDisposerCalled(); + assert !HowlingDog.closed; + producer.dispose(dog); + assert DogProducer.isHowlingDogDisposerCalled(); + assert HowlingDog.closed; + } + @Test @SpecAssertions({ @SpecAssertion(section = INJECTIONTARGET, id = "g") }) public void testInjectionPointsForProducerMethod() { diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/VocalDog.java b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/VocalDog.java new file mode 100644 index 000000000..b4fde1d0b --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/full/extensions/producer/VocalDog.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.full.extensions.producer; + +public class VocalDog { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/JumpingSpider.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/JumpingSpider.java new file mode 100644 index 000000000..46d426595 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/JumpingSpider.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.producer.field.lifecycle; + +public class JumpingSpider { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/JumpingSpiderCloseable.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/JumpingSpiderCloseable.java new file mode 100644 index 000000000..efb1da813 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/JumpingSpiderCloseable.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.producer.field.lifecycle; + +public class JumpingSpiderCloseable implements AutoCloseable { + private static boolean closed = false; + + @Override + public void close() throws Exception { + assert JumpingSpiderCloseableProducer.isDisposerCalled(); + assert !closed; + closed = true; + } + + public static boolean isClosed() { + return closed; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/JumpingSpiderCloseableProducer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/JumpingSpiderCloseableProducer.java new file mode 100644 index 000000000..418dfd642 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/JumpingSpiderCloseableProducer.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.producer.field.lifecycle; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Disposes; +import jakarta.enterprise.inject.Produces; + +@ApplicationScoped +public class JumpingSpiderCloseableProducer { + private static boolean disposerCalled = false; + + @Produces + @Dependent + @AutoClose + JumpingSpiderCloseable produce = new JumpingSpiderCloseable(); + + void dispose(@Disposes JumpingSpiderCloseable spider) { + assert !disposerCalled; + assert !JumpingSpiderCloseable.isClosed(); + disposerCalled = true; + } + + public static boolean isDisposerCalled() { + return disposerCalled; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/JumpingSpiderProducer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/JumpingSpiderProducer.java new file mode 100644 index 000000000..e0fd329c3 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/JumpingSpiderProducer.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.producer.field.lifecycle; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Disposes; +import jakarta.enterprise.inject.Produces; + +@ApplicationScoped +public class JumpingSpiderProducer { + private static boolean disposerCalled = false; + + @Produces + @Dependent + @AutoClose + JumpingSpider produce = new JumpingSpider(); + + void dispose(@Disposes JumpingSpider spider) { + assert !disposerCalled; + disposerCalled = true; + } + + public static boolean isDisposerCalled() { + return disposerCalled; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/ProducerFieldLifecycleTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/ProducerFieldLifecycleTest.java index 044d1b28f..2d7674149 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/ProducerFieldLifecycleTest.java +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/field/lifecycle/ProducerFieldLifecycleTest.java @@ -36,11 +36,8 @@ @SpecVersion(spec = "cdi", version = "2.0") public class ProducerFieldLifecycleTest extends AbstractTest { - @SuppressWarnings("serial") private AnnotationLiteral NULL_LITERAL = new Null.Literal(); - @SuppressWarnings("serial") private AnnotationLiteral BROKEN_LITERAL = new Broken.Literal(); - @SuppressWarnings("serial") private AnnotationLiteral TAME_LITERAL = new Tame.Literal(); @Deployment @@ -116,4 +113,28 @@ public void testProducerFieldBeanDestroy() throws Exception { assertTrue(BlackWidowProducer.blackWidowDestroyed); assertEquals(BlackWidowProducer.destroyedBlackWidowTimeOfBirth, instance.getTimeOfBirth()); } + + @Test + @SpecAssertion(section = PRODUCER_FIELD_LIFECYCLE, id = "pa") + public void testProducerFieldBeanDestroyWithAutoClose() { + Bean bean = getUniqueBean(JumpingSpiderCloseable.class); + CreationalContext cc = getCurrentManager().createCreationalContext(bean); + JumpingSpiderCloseable spider = bean.create(cc); + assert !JumpingSpiderCloseableProducer.isDisposerCalled(); + assert !JumpingSpiderCloseable.isClosed(); + bean.destroy(spider, cc); + assert JumpingSpiderCloseableProducer.isDisposerCalled(); + assert JumpingSpiderCloseable.isClosed(); + } + + @Test + @SpecAssertion(section = PRODUCER_FIELD_LIFECYCLE, id = "pb") + public void testProducerFieldBeanDestroyWithoutAutoClose() { + Bean bean = getUniqueBean(JumpingSpider.class); + CreationalContext cc = getCurrentManager().createCreationalContext(bean); + JumpingSpider spider = bean.create(cc); + assert !JumpingSpiderProducer.isDisposerCalled(); + bean.destroy(spider, cc); + assert JumpingSpiderProducer.isDisposerCalled(); + } } diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/JumpingSpider.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/JumpingSpider.java new file mode 100644 index 000000000..b4b73de46 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/JumpingSpider.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.producer.method.lifecycle; + +public class JumpingSpider { + private final Venom venom; + + public JumpingSpider(Venom venom) { + this.venom = venom; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/JumpingSpiderCloseable.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/JumpingSpiderCloseable.java new file mode 100644 index 000000000..36aee1751 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/JumpingSpiderCloseable.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.producer.method.lifecycle; + +public class JumpingSpiderCloseable implements AutoCloseable { + private static boolean closed = false; + + private final Venom venom; + + public JumpingSpiderCloseable(Venom venom) { + this.venom = venom; + } + + @Override + public void close() throws Exception { + assert JumpingSpiderCloseableProducer.isDisposerCalled(); + assert !closed; + assert !Venom.isDestroyed(); + closed = true; + } + + public static boolean isClosed() { + return closed; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/JumpingSpiderCloseableProducer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/JumpingSpiderCloseableProducer.java new file mode 100644 index 000000000..c7ee70921 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/JumpingSpiderCloseableProducer.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.producer.method.lifecycle; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Disposes; +import jakarta.enterprise.inject.Produces; + +@ApplicationScoped +public class JumpingSpiderCloseableProducer { + private static boolean disposerCalled = false; + + @Produces + @Dependent + @AutoClose + JumpingSpiderCloseable produce(Venom venom) { + return new JumpingSpiderCloseable(venom); + } + + void dispose(@Disposes JumpingSpiderCloseable spider) { + assert !disposerCalled; + assert !JumpingSpiderCloseable.isClosed(); + assert !Venom.isDestroyed(); + disposerCalled = true; + } + + public static boolean isDisposerCalled() { + return disposerCalled; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/JumpingSpiderProducer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/JumpingSpiderProducer.java new file mode 100644 index 000000000..eddee994b --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/JumpingSpiderProducer.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.producer.method.lifecycle; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Disposes; +import jakarta.enterprise.inject.Produces; + +@ApplicationScoped +public class JumpingSpiderProducer { + private static boolean disposerCalled = false; + + @Produces + @Dependent + @AutoClose + JumpingSpider produce(Venom venom) { + return new JumpingSpider(venom); + } + + void dispose(@Disposes JumpingSpider spider) { + assert !disposerCalled; + assert !Venom.isDestroyed(); + disposerCalled = true; + } + + public static boolean isDisposerCalled() { + return disposerCalled; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/ProducerMethodLifecycleTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/ProducerMethodLifecycleTest.java index bd97cc97b..b1914a294 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/ProducerMethodLifecycleTest.java +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/ProducerMethodLifecycleTest.java @@ -121,6 +121,38 @@ public void testProducerMethodBeanDestroy() { assert SpiderProducer.getInjectedWeb().isDestroyed(); } + @Test + @SpecAssertion(section = PRODUCER_METHOD_LIFECYCLE, id = "ma") + @SpecAssertion(section = PRODUCER_METHOD_LIFECYCLE, id = "na") + @SpecAssertion(section = PRODUCER_METHOD_LIFECYCLE, id = "r") + public void testProducerMethodBeanDestroyWithAutoClose() { + Bean bean = getUniqueBean(JumpingSpiderCloseable.class); + CreationalContext cc = getCurrentManager().createCreationalContext(bean); + JumpingSpiderCloseable spider = bean.create(cc); + assert !JumpingSpiderCloseableProducer.isDisposerCalled(); + assert !JumpingSpiderCloseable.isClosed(); + assert !Venom.isDestroyed(); + bean.destroy(spider, cc); + assert JumpingSpiderCloseableProducer.isDisposerCalled(); + assert JumpingSpiderCloseable.isClosed(); + assert Venom.isDestroyed(); + } + + @Test + @SpecAssertion(section = PRODUCER_METHOD_LIFECYCLE, id = "ma") + @SpecAssertion(section = PRODUCER_METHOD_LIFECYCLE, id = "nb") + @SpecAssertion(section = PRODUCER_METHOD_LIFECYCLE, id = "r") + public void testProducerMethodBeanDestroyWithoutAutoClose() { + Bean bean = getUniqueBean(JumpingSpider.class); + CreationalContext cc = getCurrentManager().createCreationalContext(bean); + JumpingSpider spider = bean.create(cc); + assert !JumpingSpiderProducer.isDisposerCalled(); + assert !Venom.isDestroyed(); + bean.destroy(spider, cc); + assert JumpingSpiderProducer.isDisposerCalled(); + assert Venom.isDestroyed(); + } + @Test(expectedExceptions = FooException.class) @SpecAssertions({ @SpecAssertion(section = CONTEXTUAL, id = "aa") }) public void testCreateRethrowsUncheckedException() { diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/Venom.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/Venom.java new file mode 100644 index 000000000..1bcd71d96 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/producer/method/lifecycle/Venom.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.producer.method.lifecycle; + +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.Dependent; + +@Dependent +public class Venom { + private static boolean destroyed; + + public Venom() { + destroyed = false; + } + + @PreDestroy + public void destroy() { + destroyed = true; + } + + public static boolean isDestroyed() { + return destroyed; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/DecorativeTree.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/DecorativeTree.java new file mode 100644 index 000000000..65790c72c --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/DecorativeTree.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.simple.lifecycle; + +public class DecorativeTree { + private final TreeBranch branch; + + public DecorativeTree(TreeBranch branch) { + this.branch = branch; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/DecorativeTreeCloseable.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/DecorativeTreeCloseable.java new file mode 100644 index 000000000..c2e68f34d --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/DecorativeTreeCloseable.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.simple.lifecycle; + +public class DecorativeTreeCloseable implements AutoCloseable { + private static boolean closeCalled; + + private final TreeBranch branch; + + public DecorativeTreeCloseable(TreeBranch branch) { + closeCalled = false; + this.branch = branch; + } + + @Override + public void close() throws Exception { + assert !TreeBranch.isBeanDestroyed(); + closeCalled = true; + } + + public static boolean isCloseCalled() { + return closeCalled; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/DecorativeTreeCloseableProducer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/DecorativeTreeCloseableProducer.java new file mode 100644 index 000000000..3b62a3389 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/DecorativeTreeCloseableProducer.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.simple.lifecycle; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Disposes; +import jakarta.enterprise.inject.Produces; + +@ApplicationScoped +public class DecorativeTreeCloseableProducer { + private static boolean disposerCalled = false; + + public DecorativeTreeCloseableProducer() { + disposerCalled = false; + } + + @Produces + @Dependent + @AutoClose + DecorativeTreeCloseable produce(TreeBranch branch) { + return new DecorativeTreeCloseable(branch); + } + + void dispose(@Disposes DecorativeTreeCloseable decorativeTree) { + assert !DecorativeTreeCloseable.isCloseCalled(); + assert !TreeBranch.isBeanDestroyed(); + disposerCalled = true; + } + + public static boolean isDisposerCalled() { + return disposerCalled; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/DecorativeTreeProducer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/DecorativeTreeProducer.java new file mode 100644 index 000000000..42092c6d0 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/DecorativeTreeProducer.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.simple.lifecycle; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Disposes; +import jakarta.enterprise.inject.Produces; + +@ApplicationScoped +public class DecorativeTreeProducer { + private static boolean disposerCalled = false; + + public DecorativeTreeProducer() { + disposerCalled = false; + } + + @Produces + @Dependent + DecorativeTree produce(TreeBranch branch) { + return new DecorativeTree(branch); + } + + void dispose(@Disposes DecorativeTree decorativeTree) { + assert !TreeBranch.isBeanDestroyed(); + disposerCalled = true; + } + + public static boolean isDisposerCalled() { + return disposerCalled; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/FishPond.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/FishPond.java index 5f26ad206..df5607a29 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/FishPond.java +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/FishPond.java @@ -20,6 +20,8 @@ @Dependent public class FishPond { + private static boolean beanDestroyed; + public boolean postConstructCalled; public Animal goldfish; @@ -31,6 +33,7 @@ public class FishPond { @Inject public FishPond(Goldfish goldfish, Goose goose) { + beanDestroyed = false; this.goldfish = goldfish; this.goose = goose; } @@ -43,5 +46,10 @@ public void postConstruct() { @PreDestroy public void destroy() { assert !Salmon.isBeanDestroyed(); + beanDestroyed = true; + } + + public static boolean isBeanDestroyed() { + return beanDestroyed; } } diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/FishPondCloseable.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/FishPondCloseable.java new file mode 100644 index 000000000..41ae9e9fd --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/FishPondCloseable.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.simple.lifecycle; + +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; + +@Dependent +@AutoClose +public class FishPondCloseable implements AutoCloseable { + private static boolean beanDestroyed; + private static boolean beanClosed; + + @Inject + public Salmon salmon; + + public FishPondCloseable() { + beanDestroyed = false; + beanClosed = false; + } + + @PreDestroy + public void destroy() { + assert !beanDestroyed; + assert !beanClosed; + assert !Salmon.isBeanDestroyed(); + beanDestroyed = true; + } + + @Override + public void close() throws Exception { + assert beanDestroyed; + assert !beanClosed; + assert !Salmon.isBeanDestroyed(); + beanClosed = true; + } + + public static boolean isBeanDestroyed() { + return beanDestroyed; + } + + public static boolean isBeanClosed() { + return beanClosed; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/SimpleBeanLifecycleTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/SimpleBeanLifecycleTest.java index b04c6b421..074941a95 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/SimpleBeanLifecycleTest.java +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/SimpleBeanLifecycleTest.java @@ -189,15 +189,53 @@ public void testContextualDestroyCatchesException() { } @Test - @SpecAssertions({ @SpecAssertion(section = DEPENDENT_OBJECTS_DESTRUCTION, id = "a") }) + @SpecAssertion(section = DEPENDENT_OBJECTS_DESTRUCTION, id = "aa") + @SpecAssertion(section = MANAGED_BEAN_LIFECYCLE, id = "ba") public void testDependentsDestroyedAfterPreDestroy() { Bean pondBean = getBeans(FishPond.class).iterator().next(); CreationalContext creationalContext = getCurrentManager().createCreationalContext(pondBean); FishPond fishPond = pondBean.create(creationalContext); pondBean.destroy(fishPond, creationalContext); + assert FishPond.isBeanDestroyed(); assert Salmon.isBeanDestroyed(); } + @Test + @SpecAssertion(section = DEPENDENT_OBJECTS_DESTRUCTION, id = "ab") + @SpecAssertion(section = MANAGED_BEAN_LIFECYCLE, id = "ba") + public void testDependentsDestroyedAfterPreDestroyAndAutoClose() { + Bean pondBean = getBeans(FishPondCloseable.class).iterator().next(); + CreationalContext creationalContext = getCurrentManager().createCreationalContext(pondBean); + FishPondCloseable fishPond = pondBean.create(creationalContext); + pondBean.destroy(fishPond, creationalContext); + assert FishPondCloseable.isBeanDestroyed(); + assert FishPondCloseable.isBeanClosed(); + assert Salmon.isBeanDestroyed(); + } + + @Test + @SpecAssertion(section = DEPENDENT_OBJECTS_DESTRUCTION, id = "ac") + public void testDependentsDestroyedAfterDisposer() { + Bean treeBean = getBeans(DecorativeTree.class).iterator().next(); + CreationalContext creationalContext = getCurrentManager().createCreationalContext(treeBean); + DecorativeTree decorativeTree = treeBean.create(creationalContext); + treeBean.destroy(decorativeTree, creationalContext); + assert DecorativeTreeProducer.isDisposerCalled(); + assert TreeBranch.isBeanDestroyed(); + } + + @Test + @SpecAssertion(section = DEPENDENT_OBJECTS_DESTRUCTION, id = "ad") + public void testDependentsDestroyedAfterDisposerAndAutoClose() { + Bean treeBean = getBeans(DecorativeTreeCloseable.class).iterator().next(); + CreationalContext creationalContext = getCurrentManager().createCreationalContext(treeBean); + DecorativeTreeCloseable decorativeTree = treeBean.create(creationalContext); + treeBean.destroy(decorativeTree, creationalContext); + assert DecorativeTreeCloseableProducer.isDisposerCalled(); + assert DecorativeTreeCloseable.isCloseCalled(); + assert TreeBranch.isBeanDestroyed(); + } + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) @SpecAssertion(section = MEMBER_LEVEL_INHERITANCE, id = "baa") public void testSubClassInheritsPostConstructOnSuperclass(Instance instance) { diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/TreeBranch.java b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/TreeBranch.java new file mode 100644 index 000000000..cc051fc93 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/implementation/simple/lifecycle/TreeBranch.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.implementation.simple.lifecycle; + +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.Dependent; + +@Dependent +public class TreeBranch { + private static boolean beanDestroyed = false; + + public TreeBranch() { + beanDestroyed = false; + } + + @PreDestroy + public void destroy() { + beanDestroyed = true; + } + + public static boolean isBeanDestroyed() { + return beanDestroyed; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/interceptors/invocation/InterceptorInvocationTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/interceptors/invocation/InterceptorInvocationTest.java index 5941b5f7a..ddcab1c7e 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/tests/interceptors/invocation/InterceptorInvocationTest.java +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/interceptors/invocation/InterceptorInvocationTest.java @@ -20,6 +20,8 @@ import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; +import jakarta.enterprise.inject.Instance; + import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.cdi.tck.AbstractTest; import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; @@ -138,4 +140,31 @@ public void testObjectMethodsAreNotIntercepted() { assertTrue(AlmightyInterceptor.lifecycleCallbackIntercepted); } + @Test + @SpecAssertion(section = BIZ_METHOD, id = "n") + public void testCloseIsNotInterceptedDuringDestruction() { + AlmightyInterceptor.reset(); + + Instance instance = getCurrentBeanContainer().createInstance(); + + MissileCloseable missile = instance.select(MissileCloseable.class).get(); + assertFalse(missile.closed); + + missile.close(); + + assertTrue(missile.closed); + assertTrue(AlmightyInterceptor.methodIntercepted); + + missile.reset(); + AlmightyInterceptor.reset(); + + assertFalse(missile.closed); + assertFalse(AlmightyInterceptor.methodIntercepted); + + instance.destroy(missile); + + assertTrue(missile.closed); + assertFalse(AlmightyInterceptor.methodIntercepted); + } + } diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/interceptors/invocation/MissileCloseable.java b/impl/src/main/java/org/jboss/cdi/tck/tests/interceptors/invocation/MissileCloseable.java new file mode 100644 index 000000000..b4f3cea76 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/interceptors/invocation/MissileCloseable.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * Apache Software License 2.0 which is available at: + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.cdi.tck.tests.interceptors.invocation; + +import jakarta.enterprise.context.AutoClose; +import jakarta.enterprise.context.Dependent; + +@AlmightyBinding +@AutoClose +@Dependent +public class MissileCloseable implements AutoCloseable { + boolean closed; + + public void reset() { + closed = false; + } + + @Override + public void close() { + closed = true; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/util/ActionSequence.java b/impl/src/main/java/org/jboss/cdi/tck/util/ActionSequence.java index 959b7fb63..79270c7b6 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/util/ActionSequence.java +++ b/impl/src/main/java/org/jboss/cdi/tck/util/ActionSequence.java @@ -35,21 +35,12 @@ */ public final class ActionSequence { - private static final Pattern VALID_NAME_PATTERN = Pattern.compile("[a-zA-Z0-9_.$\\-]+"); - - private static final TransformationUtils.Function, String> GET_SIMPLE_NAME = new TransformationUtils.Function, String>() { - @Override - public String apply(Class input) { - return input.getSimpleName(); - } - }; - private String name; /** * Data - list of actions */ - private List data = Collections.synchronizedList(new ArrayList()); + private final List data = Collections.synchronizedList(new ArrayList<>()); public ActionSequence() { super(); @@ -79,7 +70,7 @@ public ActionSequence add(String actionId) { * @return read-only copy of sequence data */ public List getData() { - return Collections.unmodifiableList(new ArrayList(this.data)); + return List.copyOf(this.data); } /** @@ -92,7 +83,7 @@ public String getName() { /** * * @param actions - * @return true if sequence data contain all of the specified actions, false otherwise + * @return true if sequence data contain all specified actions, false otherwise */ public boolean containsAll(String... actions) { return getData().containsAll(Arrays.asList(actions)); @@ -182,7 +173,7 @@ public void assertDataEquals(String... expected) { * @param expected */ public void assertDataEquals(Class... expected) { - assertDataEquals(TransformationUtils.transform(GET_SIMPLE_NAME, expected)); + assertDataEquals(Arrays.stream(expected).map(Class::getSimpleName).toList()); } /** @@ -214,17 +205,19 @@ public void assertDataContainsAll(String... expected) { * @param expected */ public void assertDataContainsAll(Class... expected) { - assertDataContainsAll(TransformationUtils.transform(GET_SIMPLE_NAME, expected)); + assertDataContainsAll(Arrays.stream(expected).map(Class::getSimpleName).toList()); } // Static members + private static final Pattern VALID_NAME_PATTERN = Pattern.compile("[a-zA-Z0-9_.$\\-]+"); + private static final String DEFAULT_SEQUENCE = "default"; /** * Static sequence map */ - private static Map sequences = new HashMap(); + private static final Map sequences = new HashMap<>(); /** * Remove all sequences. @@ -331,8 +324,7 @@ public static ActionSequence buildFromCsvData(String csv) { ActionSequence sequence = new ActionSequence(); - if (csv.length() != 0) { - + if (!csv.isEmpty()) { String[] data = csv.split(","); for (String actionId : data) { sequence.add(actionId); diff --git a/impl/src/main/java/org/jboss/cdi/tck/util/TransformationUtils.java b/impl/src/main/java/org/jboss/cdi/tck/util/TransformationUtils.java deleted file mode 100644 index 43b23c73b..000000000 --- a/impl/src/main/java/org/jboss/cdi/tck/util/TransformationUtils.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2010, Red Hat, Inc., and individual contributors - * - * 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.jboss.cdi.tck.util; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -public final class TransformationUtils { - - /** - * @param the input type of this function - * @param the output type of this function - */ - public static interface Function { - /** - * Returns the result of applying this function to {@code input}. - */ - T apply(F input); - } - - /** - * Returns a list that applies {@code function} to each element of {@code fromCollection}. - * - * @throws IllegalArgumentException in case of a null argument - */ - public static List transform(final Function function, - final Collection fromCollection) { - checkNotNull(fromCollection); - checkNotNull(function); - List result = new ArrayList(fromCollection.size()); - for (F element : fromCollection) { - result.add(function.apply(element)); - } - return result; - } - - /** - * Returns a list that applies {@code function} to each element of {@code inputElements}. - */ - @SafeVarargs - public static List transform(final Function function, final F... inputElements) { - return transform(function, Arrays.asList(inputElements)); - } - - private static void checkNotNull(Object o) { - if (o == null) { - throw new IllegalArgumentException("Null argument."); - } - } -} diff --git a/impl/src/main/resources/tck-audit-cdi.xml b/impl/src/main/resources/tck-audit-cdi.xml index fef5513c9..3e3ebf00b 100644 --- a/impl/src/main/resources/tck-audit-cdi.xml +++ b/impl/src/main/resources/tck-audit-cdi.xml @@ -704,6 +704,34 @@ + +
+ + + A bean class of a managed bean, a producer method and a producer field may be annotated |@AutoClose|. + This annotation marks the bean as _auto-closeable_. + + + Test with managed bean. + + + Test with producer method. + + + Test with producer field. + + + + + + If the class of a contextual instance of an auto-closeable bean implements the |java.lang.AutoCloseable| interface, + the |close()| method is called on the instance during destruction. + + +
+
@@ -726,6 +754,10 @@ A stereotype may specify that all beans with the stereotype are eagerly initialized. + + A stereotype may specify that all beans with the stereotype are auto-closeable. + + A bean may declare zero, one or multiple stereotypes. @@ -883,6 +915,12 @@
+
+ + A stereotype may declare an |@AutoClose| annotation, which specifies that every bean with the stereotype is auto-closeable. + +
+
A stereotype may declare other stereotypes. @@ -3156,11 +3194,24 @@
- - When the container destroys an instance of a bean, the container destroys all dependent objects, as defined in Section 6.4.2, "Destruction of - objects with scope @Dependent", after the |@PreDestroy| callback completes. + + + When the container destroys an instance of a bean, the container destroys all dependent objects, after + the |@PreDestroy| callback or disposer method completes and after the possible |AutoCloseable.close()| call returns. - + + Test with |@PreDestroy| callback, without |AutoCloseable.close()|. + + + Test with |@PreDestroy| callback, with |AutoCloseable.close()|. + + + Test with disposer method, without |AutoCloseable.close()|. + + +
@@ -4938,6 +4989,10 @@ Invocations of methods declared by |java.lang.Object| are not business method invocations. + + Invocations of |AutoCloseable.close()| on auto-closeable beans during destruction are not business method invocations. + + If, and only if, the invocation is a business method invocation it passes through method interceptors and decorators. @@ -4971,8 +5026,10 @@ - When the |destroy()| method is called, the container destroys the instance, as defined by the Managed Beans specification, and any dependent - objects, as defined in Section 5.5.3, "Destruction of dependent objects". + + When the |destroy()| method is called, the container destroys the instance. + Then, if the managed bean is auto-closeable and the class of the contextual instance implements |AutoCloseable|, the |close()| method is called on the instance. + Finally, the container destroys dependent objects.
@@ -5004,6 +5061,19 @@ + + + Then, if the producer method bean is auto-closeable and the class of the contextual instance implements |AutoCloseable|, + the |close()| method is called on the instance. + + + Test with instance that implements |AutoCloseable|. + + + Test with instance that does not implement |AutoCloseable|. + + + Finally, the container destroys dependent objects, as defined in Section 5.5.3, "Destruction of dependent objects". @@ -5035,6 +5105,19 @@ parameter. + + + + Then, if the producer field bean is auto-closeable and the class of the contextual instance implements |AutoCloseable|, + the |close()| method is called on the instance. + + + Test with instance that implements |AutoCloseable|. + + + Test with instance that does not implements |AutoCloseable|. + +
@@ -6741,6 +6824,10 @@ |isEager()| must return |true| if the bean is eagerly initialized, and |false| otherwise. + + |isAutoClose()| must return |true| if the bean is auto-closeable, and |false| otherwise. + + @@ -6876,9 +6963,9 @@ - For a |Producer| that represents a class, |produce()| calls the constructor annotated |@Inject| if it exists, or the constructor with no - parameters otherwise, as defined in Section 5.5.1, "Injection using the bean constructor". and returns the resulting instance. If the class has - interceptors, |produce()| is responsible for building the interceptors and decorators of the instance. + For a |Producer| that represents a managed bean, |produce()| calls the constructor annotated |@Inject| if it exists, or the constructor with no + parameters otherwise, as defined in Section 5.5.1, "Injection using the bean constructor". and returns the resulting instance. If the bean has + interceptors or decorators, |produce()| is responsible for building the interceptors and decorators of the instance. Test field injection occurs @@ -6899,11 +6986,11 @@ - For a |Producer| that represents a class, |dispose()| does nothing. + For a |Producer| that represents a managed bean, |dispose()| only does one thing: if the bean is auto-closeable and the class of the contextual instance of the bean implements |AutoCloseable|, the |close()| method is called on the instance. - For a |Producer| that represents a class, |getInjectionPoints()| returns a set of |InjectionPoint| objects representing all injected fields, + For a |Producer| that represents a managed bean, |getInjectionPoints()| returns a set of |InjectionPoint| objects representing all injected fields, bean constructor parameters and initializer method parameters. @@ -6938,6 +7025,7 @@ For a Producer that represents a producer method or field, |dispose()| calls the disposer method, if any, on a contextual instance of the bean that declares the disposer method, as defined in Section 5.5.4, "Invocation of producer or disposer methods", or performs any additional required cleanup, if any, to destroy state associated with a resource. + Then, if the bean is auto-closeable and the class of the contextual instance of the bean implements |AutoCloseable|, the |close()| method is called on the instance.