diff --git a/integrations/cdi/datasource-hikaricp/src/main/java/io/helidon/integrations/datasource/hikaricp/cdi/HikariCPBackedDataSourceExtension.java b/integrations/cdi/datasource-hikaricp/src/main/java/io/helidon/integrations/datasource/hikaricp/cdi/HikariCPBackedDataSourceExtension.java index 6288ab8ca..bd5266068 100644 --- a/integrations/cdi/datasource-hikaricp/src/main/java/io/helidon/integrations/datasource/hikaricp/cdi/HikariCPBackedDataSourceExtension.java +++ b/integrations/cdi/datasource-hikaricp/src/main/java/io/helidon/integrations/datasource/hikaricp/cdi/HikariCPBackedDataSourceExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.sql.DataSourceDefinition; +import javax.annotation.sql.DataSourceDefinitions; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; import javax.enterprise.inject.CreationException; @@ -118,7 +119,7 @@ public class HikariCPBackedDataSourceExtension extends AbstractDataSourceExtensi } private void processAnnotatedType(@Observes - @WithAnnotations(DataSourceDefinition.class) + @WithAnnotations({ DataSourceDefinition.class, DataSourceDefinitions.class }) final ProcessAnnotatedType event) { if (event != null) { final Annotated annotated = event.getAnnotatedType(); diff --git a/integrations/cdi/jpa-cdi/src/test/java/io/helidon/integrations/cdi/jpa/TestMultiplePersistenceUnits.java b/integrations/cdi/jpa-cdi/src/test/java/io/helidon/integrations/cdi/jpa/TestMultiplePersistenceUnits.java new file mode 100644 index 000000000..e457d460c --- /dev/null +++ b/integrations/cdi/jpa-cdi/src/test/java/io/helidon/integrations/cdi/jpa/TestMultiplePersistenceUnits.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. + * + * 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 io.helidon.integrations.cdi.jpa; + +import java.lang.annotation.Annotation; +import java.util.HashSet; +import java.util.Set; + +import javax.annotation.sql.DataSourceDefinition; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.BeforeDestroyed; +import javax.enterprise.event.Observes; +import javax.enterprise.inject.Instance; +import javax.enterprise.inject.se.SeContainer; +import javax.enterprise.inject.se.SeContainerInitializer; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.PersistenceContext; +import javax.persistence.PersistenceContextType; +import javax.persistence.PersistenceUnit; +import javax.persistence.SynchronizationType; +import javax.persistence.TransactionRequiredException; +import javax.transaction.Status; +import javax.transaction.SystemException; +import javax.transaction.TransactionManager; +import javax.transaction.Transactional; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +@ApplicationScoped +@DataSourceDefinition( + name = "test", + className = "org.h2.jdbcx.JdbcDataSource", + url = "jdbc:h2:mem:TestMultiplePersistenceUnits", + serverName = "", + properties = { + "user=sa" + } +) +@DataSourceDefinition( + name = "test2", + className = "org.h2.jdbcx.JdbcDataSource", + url = "jdbc:h2:mem:TestMultiplePersistenceUnits2", + serverName = "", + properties = { + "user=sa" + } +) +class TestMultiplePersistenceUnits { + + @PersistenceContext(unitName = "test") + private EntityManager testEm; + + @PersistenceContext(unitName = "test2") + private EntityManager test2Em; + + private SeContainer cdiContainer; + + TestMultiplePersistenceUnits() { + super(); + } + + @BeforeEach + void startCdiContainer() { + final SeContainerInitializer initializer = SeContainerInitializer.newInstance() + .addBeanClasses(this.getClass()); + assertNotNull(initializer); + this.cdiContainer = initializer.initialize(); + } + + @AfterEach + void shutDownCdiContainer() { + if (this.cdiContainer != null) { + this.cdiContainer.close(); + } + } + + EntityManager getTestEntityManager() { + return this.testEm; + } + + EntityManager getTest2EntityManager() { + return this.test2Em; + } + + private void onShutdown(@Observes @BeforeDestroyed(ApplicationScoped.class) final Object event, + final TransactionManager tm) throws SystemException { + // If an assertion fails, or some other error happens in the + // CDI container, there may be a current transaction that has + // neither been committed nor rolled back. Because the + // Narayana transaction engine is fundamentally static, this + // means that a transaction affiliation with the main thread + // may "leak" into another JUnit test (since JUnit, by + // default, forks once, and then runs all tests in the same + // JVM). CDI, thankfully, will fire an event for the + // application context shutting down, even in the case of + // errors. + if (tm.getStatus() != Status.STATUS_NO_TRANSACTION) { + tm.rollback(); + } + } + + @Test + void testMultiplePersistenceUnits() { + TestMultiplePersistenceUnits self = this.cdiContainer.select(TestMultiplePersistenceUnits.class).get(); + assertNotNull(self); + + EntityManager testEm = self.getTestEntityManager(); + assertNotNull(testEm); + assertTrue(testEm.isOpen()); + + EntityManager test2Em = self.getTest2EntityManager(); + assertNotNull(test2Em); + assertTrue(test2Em.isOpen()); + } + +} diff --git a/integrations/cdi/jpa-cdi/src/test/resources/META-INF/persistence.xml b/integrations/cdi/jpa-cdi/src/test/resources/META-INF/persistence.xml index 4bc081391..49c788494 100644 --- a/integrations/cdi/jpa-cdi/src/test/resources/META-INF/persistence.xml +++ b/integrations/cdi/jpa-cdi/src/test/resources/META-INF/persistence.xml @@ -37,6 +37,21 @@ + + A persistence unit for use by unit tests that is notable only for being distinguished from the test persistence unit above. + test2 + + + + + + + + + + + + A resource local persistence unit for use by unit tests.