From 7058b08fee11d4dc8ca94f34ec1a2a965170136f Mon Sep 17 00:00:00 2001 From: Johnathan Ingram Date: Thu, 11 Dec 2014 10:05:56 +0200 Subject: [PATCH 1/7] SWITCHYARD-2474 Initial project structure --- test/mixins/entitymanager/pom.xml | 48 +++++++++++++++++++ .../src/main/resources/META-INF/beans.xml | 6 +++ test/pom.xml | 1 + 3 files changed, 55 insertions(+) create mode 100644 test/mixins/entitymanager/pom.xml create mode 100644 test/mixins/entitymanager/src/main/resources/META-INF/beans.xml diff --git a/test/mixins/entitymanager/pom.xml b/test/mixins/entitymanager/pom.xml new file mode 100644 index 000000000..6d61e32d1 --- /dev/null +++ b/test/mixins/entitymanager/pom.xml @@ -0,0 +1,48 @@ + + + + 4.0.0 + + org.switchyard.components + switchyard-component-test-parent + 2.0.0-SNAPSHOT + ../../pom.xml + + switchyard-component-test-mixin-entitymanager + jar + SwitchYard: Entity Manager MixIn + Entity Manager MixIn classes + http://switchyard.org + + + org.jboss.as + jboss-as-naming + + + org.jboss.logmanager + log4j-jboss-logmanager + + + + + org.switchyard.components + switchyard-component-test-mixin-naming + + + org.switchyard.components + switchyard-component-test-mixin-jca + + + diff --git a/test/mixins/entitymanager/src/main/resources/META-INF/beans.xml b/test/mixins/entitymanager/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..1ad2e0857 --- /dev/null +++ b/test/mixins/entitymanager/src/main/resources/META-INF/beans.xml @@ -0,0 +1,6 @@ + + + diff --git a/test/pom.xml b/test/pom.xml index 61a1528ca..17993f4d0 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -34,6 +34,7 @@ mixins/http mixins/jca mixins/smooks + mixins/entitymanager From 53f9ee798bad1177f0f2b83a05e35a504ad1efd6 Mon Sep 17 00:00:00 2001 From: Johnathan Ingram Date: Thu, 11 Dec 2014 12:17:26 +0200 Subject: [PATCH 2/7] SWITCHYARD-2474 Initial port of EntityManager delegate / singleton and refactor into MixIn concept. Added creation of datasource that is transaction aware for EMF --- test/mixins/entitymanager/pom.xml | 73 ++++---- .../entitymanager/AnnotationWrappers.java | 117 ++++++++++++ .../CDIPersistenceExtension.java | 175 ++++++++++++++++++ .../entitymanager/DataSourceDelegate.java | 85 +++++++++ .../entitymanager/EntityManagerDelegate.java | 175 ++++++++++++++++++ .../entitymanager/EntityManagerMixIn.java | 145 +++++++++++++++ .../entitymanager/EntityManagerProducer.java | 67 +++++++ .../javax.enterprise.inject.spi.Extension | 1 + .../EntityManagerMixInSelfInjectTest.java | 46 +++++ 9 files changed, 852 insertions(+), 32 deletions(-) create mode 100644 test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/AnnotationWrappers.java create mode 100644 test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/CDIPersistenceExtension.java create mode 100644 test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/DataSourceDelegate.java create mode 100644 test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerDelegate.java create mode 100644 test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java create mode 100644 test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerProducer.java create mode 100644 test/mixins/entitymanager/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension create mode 100644 test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInSelfInjectTest.java diff --git a/test/mixins/entitymanager/pom.xml b/test/mixins/entitymanager/pom.xml index 6d61e32d1..6b7c01424 100644 --- a/test/mixins/entitymanager/pom.xml +++ b/test/mixins/entitymanager/pom.xml @@ -13,36 +13,45 @@ - limitations under the License. --> - 4.0.0 - - org.switchyard.components - switchyard-component-test-parent - 2.0.0-SNAPSHOT - ../../pom.xml - - switchyard-component-test-mixin-entitymanager - jar - SwitchYard: Entity Manager MixIn - Entity Manager MixIn classes - http://switchyard.org - - - org.jboss.as - jboss-as-naming - - - org.jboss.logmanager - log4j-jboss-logmanager - - - - - org.switchyard.components - switchyard-component-test-mixin-naming - - - org.switchyard.components - switchyard-component-test-mixin-jca - - + 4.0.0 + + org.switchyard.components + switchyard-component-test-parent + 2.0.0-SNAPSHOT + ../../pom.xml + + switchyard-component-test-mixin-entitymanager + jar + SwitchYard: Entity Manager MixIn + Entity Manager MixIn classes + http://switchyard.org + + + org.jboss.as + jboss-as-naming + + + org.jboss.logmanager + log4j-jboss-logmanager + + + + + org.switchyard.components + switchyard-component-test-mixin-naming + + + org.switchyard.components + switchyard-component-test-mixin-jca + + + org.hibernate.javax.persistence + hibernate-jpa-2.0-api + + + com.experlog + xapool + 1.5.0 + + diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/AnnotationWrappers.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/AnnotationWrappers.java new file mode 100644 index 000000000..49dd3166f --- /dev/null +++ b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/AnnotationWrappers.java @@ -0,0 +1,117 @@ +/* + * AnnotationWrappers.java + * + * Copyright 2014 Johnathan Ingram (jingram@rogueware.org) + * + * 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.switchyard.component.test.mixins.entitymanager; + +import java.lang.annotation.Annotation; + +/** + * + * @author Johnathan Ingram (jingram@rogueware.org) + */ +public class AnnotationWrappers { + + private AnnotationWrappers() { + } + + public static class Inject { + + @javax.inject.Inject + public static Object field; + + public static Annotation getAnnotation() { + try { + return Inject.class.getField("field").getAnnotation(javax.inject.Inject.class); + } catch (Exception ex) { + return null; + } + } + } + + @javax.inject.Named + public static class Named { + + public static Annotation getAnnotation() { + try { + return Named.class.getAnnotation(javax.inject.Named.class); + } catch (Exception ex) { + return null; + } + } + } + + @javax.inject.Singleton + public static class Singleton { + + public static Annotation getAnnotation() { + try { + return Dependent.class.getAnnotation(javax.inject.Singleton.class); + } catch (Exception ex) { + return null; + } + } + } + + @javax.enterprise.context.Dependent + public static class Dependent { + + public static Annotation getAnnotation() { + try { + return Dependent.class.getAnnotation(javax.enterprise.context.Dependent.class); + } catch (Exception ex) { + return null; + } + } + } + + @javax.enterprise.context.RequestScoped + public static class RequestScoped { + + public static Annotation getAnnotation() { + try { + return RequestScoped.class.getAnnotation(javax.enterprise.context.RequestScoped.class); + } catch (Exception ex) { + return null; + } + } + } + + @javax.enterprise.context.ApplicationScoped + public static class ApplicationScoped { + + public static Annotation getAnnotation() { + try { + return ApplicationScoped.class.getAnnotation(javax.enterprise.context.ApplicationScoped.class); + } catch (Exception ex) { + return null; + } + } + } + + @javax.enterprise.inject.Default + public static class Default { + + public static Annotation getAnnotation() { + try { + return Default.class.getAnnotation(javax.enterprise.inject.Default.class); + } catch (Exception ex) { + return null; + } + } + } +} diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/CDIPersistenceExtension.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/CDIPersistenceExtension.java new file mode 100644 index 000000000..279f073e0 --- /dev/null +++ b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/CDIPersistenceExtension.java @@ -0,0 +1,175 @@ +/* + * CDIPersistenceExtension.java + * + * Copyright 2014 Johnathan Ingram (jingram@rogueware.org) + * All rights reserved. + * + * 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.switchyard.component.test.mixins.entitymanager; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import javax.enterprise.event.Observes; +import javax.enterprise.inject.spi.AnnotatedConstructor; +import javax.enterprise.inject.spi.AnnotatedField; +import javax.enterprise.inject.spi.AnnotatedMethod; +import javax.enterprise.inject.spi.AnnotatedType; +import javax.enterprise.inject.spi.Extension; +import javax.enterprise.inject.spi.ProcessAnnotatedType; +import javax.persistence.PersistenceContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author Johnathan Ingram (jingram@rogueware.org) + */ +public class CDIPersistenceExtension implements Extension { + + private transient static final Logger log = LoggerFactory.getLogger(CDIPersistenceExtension.class); + + + // Ensure all javax.persistence.EntityManager fields with @PersistenceContext are annotated @Inject + public void processJPAAnnotations(@Observes ProcessAnnotatedType pat) { + final AnnotatedType at = pat.getAnnotatedType(); + + // Override any javax.persistence.EntityManager fields @PersistenceContext annotations with @Inject + AnnotatedType wrapped = new AnnotatedType() { + + @Override + public Class getJavaClass() { + return at.getJavaClass(); + } + + @Override + public Set> getConstructors() { + return at.getConstructors(); + } + + @Override + public Set> getMethods() { + return at.getMethods(); + } + + @Override + public Set> getFields() { + Set> result = new HashSet>(); + for (final AnnotatedField af : at.getFields()) { + // If there is a field with the @PersistenceContext of type javax.persistence.EntityManager, + // make sure the field has the @Inject + if (javax.persistence.EntityManager.class.equals(af.getJavaMember().getType()) + && af.isAnnotationPresent(PersistenceContext.class)) { + result.add(addAnnotation(af, AnnotationWrappers.Inject.getAnnotation())); + } else { + result.add(af); + } + } + + return result; + } + + @Override + public Type getBaseType() { + return at.getBaseType(); + } + + @Override + public Set getTypeClosure() { + return at.getTypeClosure(); + } + + @Override + public T getAnnotation(Class annotationType) { + return at.getAnnotation(annotationType); + } + + @Override + public Set getAnnotations() { + return at.getAnnotations(); + } + + @Override + public boolean isAnnotationPresent(Class annotationType) { + return at.isAnnotationPresent(annotationType); + } + }; + + pat.setAnnotatedType(wrapped); + } + + + public static AnnotatedField addAnnotation(final AnnotatedField af, final Annotation... annotations) { + + return new AnnotatedField() { + @Override + public Field getJavaMember() { + return af.getJavaMember(); + } + + @Override + public boolean isStatic() { + return af.isStatic(); + } + + @Override + public AnnotatedType getDeclaringType() { + return af.getDeclaringType(); + } + + @Override + public Type getBaseType() { + return af.getBaseType(); + } + + @Override + public Set getTypeClosure() { + return af.getTypeClosure(); + } + + @Override + public T getAnnotation(Class annotationType) { + for (Annotation a : annotations) { + if (a.annotationType().equals(annotationType)) { + return (T) a; + } + } + return af.getAnnotation(annotationType); + } + + @Override + public Set getAnnotations() { + Set result = new HashSet(af.getAnnotations()); + result.addAll(Arrays.asList(annotations)); + return result; + } + + @Override + public boolean isAnnotationPresent(Class annotationType) { + for (Annotation a : annotations) { + + if (a.annotationType().equals(annotationType)) { + return true; + } + } + + return af.isAnnotationPresent(annotationType); + } + }; + } +} diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/DataSourceDelegate.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/DataSourceDelegate.java new file mode 100644 index 000000000..ca43aff18 --- /dev/null +++ b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/DataSourceDelegate.java @@ -0,0 +1,85 @@ +/* + * DataSourceDelegate.java + * + * Copyright 2014 Johnathan Ingram (jingram@rogueware.org) + * + * 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.switchyard.component.test.mixins.entitymanager; + +import java.io.PrintWriter; +import java.io.Serializable; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.logging.Logger; +import javax.sql.DataSource; + +/** + * + * @author Johnathan Ingram (jingram@rogueware.org) + */ +public class DataSourceDelegate implements javax.sql.DataSource, Serializable { + + private DataSource ds; + + public DataSourceDelegate(DataSource ds) { + this.ds = ds; + } + + @Override + public Connection getConnection() throws SQLException { + return ds.getConnection(); + } + + @Override + public Connection getConnection(String username, String password) throws SQLException { + return ds.getConnection(username, password); + } + + @Override + public PrintWriter getLogWriter() throws SQLException { + return ds.getLogWriter(); + } + + @Override + public void setLogWriter(PrintWriter out) throws SQLException { + ds.setLogWriter(out); + } + + @Override + public void setLoginTimeout(int seconds) throws SQLException { + ds.setLoginTimeout(seconds); + } + + @Override + public int getLoginTimeout() throws SQLException { + return ds.getLoginTimeout(); + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + return ds.getParentLogger(); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return ds.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return ds.isWrapperFor(iface); + } +} diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerDelegate.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerDelegate.java new file mode 100644 index 000000000..2eb9cdac1 --- /dev/null +++ b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerDelegate.java @@ -0,0 +1,175 @@ +/* + * EntityManagerDelegate.java + * + * Copyright 2014 Johnathan Ingram (jingram@rogueware.org) + * + * 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.switchyard.component.test.mixins.entitymanager; + +import java.io.Serializable; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import javax.persistence.EntityManager; +import javax.transaction.Status; +import javax.transaction.Synchronization; +import javax.transaction.SystemException; +import javax.transaction.TransactionManager; +import javax.transaction.TransactionRequiredException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author Johnathan Ingram (jingram@rogueware.org) + */ +public class EntityManagerDelegate implements InvocationHandler, Serializable { + + private transient static final Logger log = LoggerFactory.getLogger(EntityManagerDelegate.class); + private transient static final ThreadLocal>> threadEntityManagerByTransaction = new ThreadLocal>>(); + + private final String unitName; + + public EntityManagerDelegate(String unitName) { + this.unitName = unitName == null ? EntityManagerMixIn.getDefaultPersistenceUnitName() : unitName; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + EntityManager em = getEntityManagerForCurrentTransaction(); + try { + return method.invoke(em, args); + } catch (InvocationTargetException ex) { + throw ex.getCause(); + } + } + + private EntityManager getEntityManagerForCurrentTransaction() throws SystemException, TransactionRequiredException { + long threadId = Thread.currentThread().getId(); + EntityManager em = null; + + // Make sure we have the thread var for this thread managing entity managers + Map> emsPUs = threadEntityManagerByTransaction.get(); + if (null == emsPUs) { + emsPUs = new HashMap>(); + threadEntityManagerByTransaction.set(emsPUs); // Map scoped per thread for each PU, its thread id and em + } + + // Make sure we have a list of thread and em for this pu + Map ems; + if (!emsPUs.containsKey(unitName)) { + ems = new HashMap(); + emsPUs.put(unitName, ems); + } else { + ems = emsPUs.get(unitName); + } + + // If there is a transaction, create new entity manager for transaction or return existing one + TransactionManager tm = EntityManagerMixIn.getTransactionManager(); + if (null != tm && null != tm.getTransaction() && tm.getStatus() != Status.STATUS_NO_TRANSACTION) { + int transactionId = tm.getTransaction().hashCode(); + if (ems.containsKey(transactionId)) { + // return the existing em for the transaction + em = ems.get(transactionId); + log.trace("Returning entity manager for thread id '{}', pu '{}' and transaction id '{}'", threadId, unitName, transactionId); + } else { + // Create an em for the transaction + // Register synchronization to cleanup entity manager when transaction completes + try { + tm.getTransaction().registerSynchronization(new EntityManagerTransactionSynchronization(transactionId)); + } catch (Exception ex) { + log.error("Unable to register transaction synchronization for entity manager cleanup for thread id '{}', pu '{}' and transaction id '{}'", threadId, unitName, transactionId); + throw new IllegalStateException(String.format("Unable to register transaction synchronization for entity manager cleanup for thread id %d, pu %s and transaction id %d", threadId, unitName, transactionId)); + } + em = EntityManagerMixIn.createEntityManager(unitName); + + if (null != em) { + ems.put(transactionId, em); + em.joinTransaction(); + + log.trace("Created entity manager for thread id '{}', pu '{}' and transaction id '{}'", threadId, unitName, transactionId); + } else { + log.warn("Unable to create entity manager for thread id '{}', pu '{}' and transaction id '{}'", threadId, unitName, transactionId); + } + } + } else { + // No transaction + throw new IllegalStateException(String.format("No transaction available to scope enity manager for thread id %d", threadId)); + } + return em; + } + + private class EntityManagerTransactionSynchronization implements Synchronization { + + private final int transactionId; + + protected EntityManagerTransactionSynchronization(int transactionId) { + this.transactionId = transactionId; + } + + @Override + public void beforeCompletion() { + long threadId = Thread.currentThread().getId(); + try { + Map> emsPUs = threadEntityManagerByTransaction.get(); + if (null == emsPUs) { + return; + } + Map ems = emsPUs.get(unitName); + if (null == ems) { + return; + } + + if (ems.containsKey(transactionId)) { + EntityManager em = ems.get(transactionId); + // Make sure nothing further can happen on the entity manager + if (null != em) { + em.close(); + log.trace("Closed entity manager for thread id '{}', pu '{}' and transaction id '{}' on before transaction completion", threadId, unitName, transactionId); + } + } + } catch (Throwable ex) { + log.error("Unknown exception before transaction completion for thread id '{}', pu '{}' and transaction id '{}'", threadId, unitName, transactionId, ex); + } + } + + @Override + public void afterCompletion(int status) { + // Don't care about status, just release the entity manager associated with the transaction + long threadId = Thread.currentThread().getId(); + + try { + Map> emsPUs = threadEntityManagerByTransaction.get(); + if (null == emsPUs) { + return; + } + Map ems = emsPUs.get(unitName); + if (null == ems) { + return; + } + + if (ems.containsKey(transactionId)) { + EntityManager em = ems.remove(transactionId); + em = null; + log.trace("Deleted entity manager for thread id '{}', pu '{}' and transaction id '{}' on after transaction completion", threadId, unitName, transactionId); + } + } catch (Throwable ex) { + log.error("Unknown exception after transaction completion for thread id '{}', pu '{}' and transaction id '{}'", threadId, unitName, transactionId, ex); + } + } + } +} diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java new file mode 100644 index 000000000..ba1b1445c --- /dev/null +++ b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java @@ -0,0 +1,145 @@ +/* + * EntityManagerMixIn.java + * + * Copyright 2014 Johnathan Ingram (jingram@rogueware.org) + * + * 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.switchyard.component.test.mixins.entitymanager; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import javax.naming.InitialContext; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.sql.XADataSource; +import javax.transaction.TransactionManager; +import org.enhydra.jdbc.pool.StandardXAPoolDataSource; +import org.enhydra.jdbc.standard.StandardXADataSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.switchyard.component.test.mixins.naming.NamingMixIn; +import org.switchyard.component.test.mixins.transaction.TransactionMixIn; +import org.switchyard.test.mixins.AbstractTestMixIn; + +/** + * + * @author Johnathan Ingram (jingram@rogueware.org) + */ +public class EntityManagerMixIn extends AbstractTestMixIn { + + protected static final Logger log = LoggerFactory.getLogger(EntityManagerMixIn.class); + + private static final Map emfs = Collections.synchronizedMap(new HashMap()); + private static String primayPU; + private static TransactionMixIn transactionMixIn; + private static NamingMixIn namingMixIn; + + @Override + public void initialize() { + // Get a reference to the TransactionMixIn + transactionMixIn = getTestKit().getMixIn(TransactionMixIn.class); + if (null == transactionMixIn) { + log.error("Unable to obtain a reference to the transaction manager mix-in"); + } + namingMixIn = getTestKit().getMixIn(NamingMixIn.class); + if (null == namingMixIn) { + log.error("Unable to obtain a reference to the naming mix-in"); + } + } + + public void createEntityManagerFactory(String persistenceUnitName, String jtaDataSource, String datasourceDriverName, String datasourceUrlr, String datasourceUser, String dataSourcePassword) throws Exception { + // Create a transaction aware XA datasource and bind it to JNDI + try { + StandardXADataSource sXaDs = new StandardXADataSource(); + sXaDs.setUrl(datasourceUrlr); + sXaDs.setDriverName(datasourceDriverName); + sXaDs.setUser(datasourceUser); + sXaDs.setPassword(dataSourcePassword); + sXaDs.setTransactionManager(transactionMixIn.getTransactionManager()); + + StandardXAPoolDataSource xaPoolDS = new StandardXAPoolDataSource(); + xaPoolDS.setTransactionManager(transactionMixIn.getTransactionManager()); // Always set first + xaPoolDS.setDataSource((XADataSource) sXaDs); + xaPoolDS.setUser(datasourceUser); + xaPoolDS.setPassword(dataSourcePassword); + xaPoolDS.setMaxSize(10); + xaPoolDS.setMinSize(5); + xaPoolDS.setDeadLockMaxWait(30 * 1000); + + // Need to bind delegate DataSource + InitialContext initialContext = namingMixIn.getInitialContext(); + initialContext.bind(jtaDataSource, new DataSourceDelegate(xaPoolDS)); + } catch (Exception ex) { + log.error("Unable to create the datasource for JNDI '{}' with driver='{}'", jtaDataSource, datasourceDriverName, ex); + throw ex; + } + + // Create the entity manager factory (EMF) + try { + + EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName); + + emfs.put(persistenceUnitName, emf); + if (null == primayPU) { + primayPU = persistenceUnitName; + } + } catch (Exception ex) { + log.error("Unable to create the entity manager factory for persistence unit name '{}'", persistenceUnitName, ex); + throw ex; + } + } + + protected static String getDefaultPersistenceUnitName() { + return primayPU; + } + + protected static EntityManagerFactory getEntityManagerFactory() { + if (null != primayPU) { + return emfs.get(primayPU); + } else { + log.error("Unable to obtain the default entity manager as no entity manager factories have been set with 'createEntityManagerFactory'"); + return null; + } + } + + protected static EntityManagerFactory getEntityManagerFactory(String pu) { + if (emfs.containsKey(pu)) { + return emfs.get(pu); + } else { + log.error("Unable to obtain entity manager for persistence unit '{}' as no entity manager factory has been set", pu); + return null; + } + } + + protected static EntityManager createEntityManager(String persistenceUnitName) { + EntityManagerFactory emf = null; + if (null == (emf = emfs.get(persistenceUnitName))) { + return null; + } + EntityManager em = emf.createEntityManager(); + return em; + } + + protected static TransactionManager getTransactionManager() { + if (null != transactionMixIn || null == transactionMixIn.getTransactionManager()) { + return transactionMixIn.getTransactionManager(); + } else { + log.error("Unable to obtain transaction manager as either transaction mix-in or transaction manager is null"); + return null; + } + } +} diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerProducer.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerProducer.java new file mode 100644 index 000000000..80a6e5000 --- /dev/null +++ b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerProducer.java @@ -0,0 +1,67 @@ +/* + * EntityManagerProducer.java + * + * Copyright 2014 Johnathan Ingram (jingram@rogueware.org) + * + * 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.switchyard.component.test.mixins.entitymanager; + +import java.io.Serializable; +import java.lang.reflect.Proxy; + +import javax.enterprise.inject.Produces; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.inject.Named; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author Johnathan Ingram (jingram@rogueware.org) + */ +public class EntityManagerProducer implements Serializable { + + private static final Logger log = LoggerFactory.getLogger(EntityManagerProducer.class); + + @Produces + @Named + public EntityManager createEntityManager(InjectionPoint injectionPoint) { + // Create the delegate to act on behald of the entity manager + // in context of a thread and transaction + String unitName = null != getUnitNameFromAnnotation(injectionPoint) ? getUnitNameFromAnnotation(injectionPoint) : EntityManagerMixIn.getDefaultPersistenceUnitName(); + EntityManagerDelegate emd = new EntityManagerDelegate(unitName); + EntityManager em = (EntityManager) Proxy.newProxyInstance( + EntityManagerDelegate.class + .getClassLoader(), + new Class[]{EntityManager.class}, + emd); + + log.trace("Created entity manager delegate for pu '{}' injected into '{}' class member '{}'", unitName, injectionPoint.getMember().getDeclaringClass().getName(), injectionPoint.getMember().getName()); + return em; + } + + private String getUnitNameFromAnnotation(InjectionPoint injectionPoint) { + PersistenceContext annotation = injectionPoint.getAnnotated().getAnnotation(PersistenceContext.class); + if (null != annotation) { + if (null != annotation.unitName() && 0 != annotation.unitName().length()) { + return annotation.unitName(); + } + } + return null; + } +} diff --git a/test/mixins/entitymanager/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/test/mixins/entitymanager/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension new file mode 100644 index 000000000..d90ce883d --- /dev/null +++ b/test/mixins/entitymanager/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension @@ -0,0 +1 @@ +org.switchyard.component.test.mixins.entitymanager.CDIPersistenceExtension \ No newline at end of file diff --git a/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInSelfInjectTest.java b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInSelfInjectTest.java new file mode 100644 index 000000000..3ec100594 --- /dev/null +++ b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInSelfInjectTest.java @@ -0,0 +1,46 @@ +/* + * + * Copyright 2014 Johnathan Ingram (jingram@rogueware.org) + * + * 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.switchyard.component.test.mixins.entitymanager; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Unit test for {@link EntityManagerQMixIn}. + * + * @author Johnathan Ingram (jingram@rogueware.org) + * + */ +public class EntityManagerMixInSelfInjectTest { + + private EntityManagerMixIn EntityManagerMixIn; + + @BeforeClass + public static void setup() { + } + + @AfterClass + public static void tearDown() { + } + + @Test + public void getClientSession() { + int i = 1; + } +} From 2d59d7fbfa5be605f8c1e8abbc150e58c19db85a Mon Sep 17 00:00:00 2001 From: Johnathan Ingram Date: Thu, 11 Dec 2014 12:30:36 +0200 Subject: [PATCH 3/7] SWITCHYARD-2474 Temporary dependency management fix Will move to parent in later commit --- test/mixins/entitymanager/pom.xml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/mixins/entitymanager/pom.xml b/test/mixins/entitymanager/pom.xml index 6b7c01424..3daed7f4b 100644 --- a/test/mixins/entitymanager/pom.xml +++ b/test/mixins/entitymanager/pom.xml @@ -25,6 +25,18 @@ SwitchYard: Entity Manager MixIn Entity Manager MixIn classes http://switchyard.org + + + + + com.experlog + xapool + 1.5.0 + + + + + org.jboss.as @@ -51,7 +63,6 @@ com.experlog xapool - 1.5.0 From 6dfaa5aa0c6a955d686d9abf3c3194c9f68f3f41 Mon Sep 17 00:00:00 2001 From: Johnathan Ingram Date: Thu, 11 Dec 2014 13:27:57 +0200 Subject: [PATCH 4/7] SWITCHYARD-2474 Basic test --- test/mixins/entitymanager/pom.xml | 55 ++++++++++++++++++- .../entitymanager/EntityManagerMixIn.java | 11 ++-- .../src/main/resources/META-INF/beans.xml | 6 -- .../test/mixins/entitymanager/BasicBean.java | 28 ++++++++++ .../EntityManagerMixInSelfInjectTest.java | 46 ++++++++++------ .../src/test/resources/META-INF/beans.xml | 0 .../test/resources/META-INF/persistence.xml | 9 +++ 7 files changed, 127 insertions(+), 28 deletions(-) create mode 100644 test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/BasicBean.java create mode 100644 test/mixins/entitymanager/src/test/resources/META-INF/beans.xml create mode 100644 test/mixins/entitymanager/src/test/resources/META-INF/persistence.xml diff --git a/test/mixins/entitymanager/pom.xml b/test/mixins/entitymanager/pom.xml index 3daed7f4b..ef4dce61d 100644 --- a/test/mixins/entitymanager/pom.xml +++ b/test/mixins/entitymanager/pom.xml @@ -28,6 +28,12 @@ + + com.h2database + h2 + 1.4.181 + + com.experlog xapool @@ -38,6 +44,24 @@ + + + org.switchyard + switchyard-api + + + org.switchyard + switchyard-common + + + + + + com.h2database + h2 + test + + org.jboss.as jboss-as-naming @@ -48,6 +72,10 @@ + + org.switchyard.components + switchyard-component-test-mixin-cdi + org.switchyard.components switchyard-component-test-mixin-naming @@ -56,10 +84,35 @@ org.switchyard.components switchyard-component-test-mixin-jca + + org.switchyard.components + switchyard-component-bean + test + + org.hibernate.javax.persistence hibernate-jpa-2.0-api - + + + org.hibernate + hibernate-entitymanager + + + + + + org.jboss.spec.javax.resource + jboss-connector-api_1.6_spec + + + org.jboss.weld.se + weld-se-core + + + org.jboss.weld + weld-spi + com.experlog xapool diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java index ba1b1445c..a0a26d77a 100644 --- a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java +++ b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java @@ -51,12 +51,15 @@ public class EntityManagerMixIn extends AbstractTestMixIn { @Override public void initialize() { // Get a reference to the TransactionMixIn - transactionMixIn = getTestKit().getMixIn(TransactionMixIn.class); - if (null == transactionMixIn) { + try { + transactionMixIn = getTestKit().getMixIn(TransactionMixIn.class); + } catch (Exception ex) { log.error("Unable to obtain a reference to the transaction manager mix-in"); } - namingMixIn = getTestKit().getMixIn(NamingMixIn.class); - if (null == namingMixIn) { + + try { + namingMixIn = getTestKit().getMixIn(NamingMixIn.class); + } catch (Exception ex) { log.error("Unable to obtain a reference to the naming mix-in"); } } diff --git a/test/mixins/entitymanager/src/main/resources/META-INF/beans.xml b/test/mixins/entitymanager/src/main/resources/META-INF/beans.xml index 1ad2e0857..e69de29bb 100644 --- a/test/mixins/entitymanager/src/main/resources/META-INF/beans.xml +++ b/test/mixins/entitymanager/src/main/resources/META-INF/beans.xml @@ -1,6 +0,0 @@ - - - diff --git a/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/BasicBean.java b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/BasicBean.java new file mode 100644 index 000000000..96cc38f2b --- /dev/null +++ b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/BasicBean.java @@ -0,0 +1,28 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.switchyard.component.test.mixins.entitymanager; + +import javax.enterprise.inject.Default; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +/** + * + * @author jingram + */ +@Default +public class BasicBean { + + @PersistenceContext + private EntityManager em; + + public EntityManager getEm() { + return em; + } + + + +} diff --git a/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInSelfInjectTest.java b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInSelfInjectTest.java index 3ec100594..855f2ffac 100644 --- a/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInSelfInjectTest.java +++ b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInSelfInjectTest.java @@ -17,30 +17,42 @@ */ package org.switchyard.component.test.mixins.entitymanager; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import javax.inject.Inject; +import static org.junit.Assert.assertNotNull; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.switchyard.component.test.mixins.cdi.CDIMixIn; +import org.switchyard.component.test.mixins.naming.NamingMixIn; +import org.switchyard.component.test.mixins.transaction.TransactionMixIn; +import org.switchyard.test.SwitchYardRunner; +import org.switchyard.test.SwitchYardTestCaseConfig; /** * Unit test for {@link EntityManagerQMixIn}. - * + * * @author Johnathan Ingram (jingram@rogueware.org) * */ +@RunWith(SwitchYardRunner.class) +@SwitchYardTestCaseConfig(mixins = {CDIMixIn.class, NamingMixIn.class, TransactionMixIn.class, EntityManagerMixIn.class}) public class EntityManagerMixInSelfInjectTest { - - private EntityManagerMixIn EntityManagerMixIn; - - @BeforeClass - public static void setup() { - } - - @AfterClass - public static void tearDown() { - } - @Test - public void getClientSession() { - int i = 1; - } + //private NamingMixIn namingMixIn; + //private TransactionMixIn transactionMixIn; + private EntityManagerMixIn entityManagerMixIn; + + @Inject + BasicBean tb; + + @Before + public void setup() throws Exception { + entityManagerMixIn.createEntityManagerFactory("mixin-test-one", "java:jboss/datasources/MixInTestOne", "org.h2.Driver", "jdbc:h2:mem:testDB-one", "sa", "sa"); + } + + @Test + public void getClientSession() { + assertNotNull("Entity Manager not injected", tb.getEm()); + } + } diff --git a/test/mixins/entitymanager/src/test/resources/META-INF/beans.xml b/test/mixins/entitymanager/src/test/resources/META-INF/beans.xml new file mode 100644 index 000000000..e69de29bb diff --git a/test/mixins/entitymanager/src/test/resources/META-INF/persistence.xml b/test/mixins/entitymanager/src/test/resources/META-INF/persistence.xml new file mode 100644 index 000000000..b8bfccb2e --- /dev/null +++ b/test/mixins/entitymanager/src/test/resources/META-INF/persistence.xml @@ -0,0 +1,9 @@ + + + + org.hibernate.ejb.HibernatePersistence + java:jboss/datasources/MixInTestOne + + + + From 634746316233e8791f72b7ed87731ce1acfb9ccd Mon Sep 17 00:00:00 2001 From: Rainer Schamm Date: Thu, 11 Dec 2014 16:43:06 +0200 Subject: [PATCH 5/7] SWITCHYARD-2474 Adding proper test for EntityManager mixin --- .../entitymanager/EntityManagerDelegate.java | 7 +- .../entitymanager/EntityManagerMixIn.java | 15 +- .../test/mixins/entitymanager/BasicBean.java | 66 ++++++-- .../test/mixins/entitymanager/BasicTable.java | 120 +++++++++++++ .../EntityManagerMixInSelfInjectTest.java | 58 ------- .../entitymanager/EntityManagerMixInTest.java | 160 ++++++++++++++++++ .../test/resources/META-INF/persistence.xml | 28 ++- 7 files changed, 369 insertions(+), 85 deletions(-) create mode 100644 test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/BasicTable.java delete mode 100644 test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInSelfInjectTest.java create mode 100644 test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInTest.java diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerDelegate.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerDelegate.java index 2eb9cdac1..b0b9ba7c4 100644 --- a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerDelegate.java +++ b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerDelegate.java @@ -42,10 +42,10 @@ public class EntityManagerDelegate implements InvocationHandler, Serializable { private transient static final Logger log = LoggerFactory.getLogger(EntityManagerDelegate.class); private transient static final ThreadLocal>> threadEntityManagerByTransaction = new ThreadLocal>>(); - private final String unitName; + private String unitName; public EntityManagerDelegate(String unitName) { - this.unitName = unitName == null ? EntityManagerMixIn.getDefaultPersistenceUnitName() : unitName; + this.unitName = unitName; } @Override @@ -59,6 +59,9 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl } private EntityManager getEntityManagerForCurrentTransaction() throws SystemException, TransactionRequiredException { + if (null == unitName) { + unitName = EntityManagerMixIn.getDefaultPersistenceUnitName(); + } long threadId = Thread.currentThread().getId(); EntityManager em = null; diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java index a0a26d77a..15931c5e7 100644 --- a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java +++ b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import javax.naming.InitialContext; import javax.persistence.EntityManager; @@ -43,8 +44,8 @@ public class EntityManagerMixIn extends AbstractTestMixIn { protected static final Logger log = LoggerFactory.getLogger(EntityManagerMixIn.class); - private static final Map emfs = Collections.synchronizedMap(new HashMap()); - private static String primayPU; + private static final Map emfs = Collections.synchronizedMap(new LinkedHashMap()); + private static String primaryPU; private static TransactionMixIn transactionMixIn; private static NamingMixIn namingMixIn; @@ -97,8 +98,8 @@ public void createEntityManagerFactory(String persistenceUnitName, String jtaDat EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName); emfs.put(persistenceUnitName, emf); - if (null == primayPU) { - primayPU = persistenceUnitName; + if (null == primaryPU) { + primaryPU = persistenceUnitName; } } catch (Exception ex) { log.error("Unable to create the entity manager factory for persistence unit name '{}'", persistenceUnitName, ex); @@ -107,12 +108,12 @@ public void createEntityManagerFactory(String persistenceUnitName, String jtaDat } protected static String getDefaultPersistenceUnitName() { - return primayPU; + return primaryPU; } protected static EntityManagerFactory getEntityManagerFactory() { - if (null != primayPU) { - return emfs.get(primayPU); + if (null != primaryPU) { + return emfs.get(primaryPU); } else { log.error("Unable to obtain the default entity manager as no entity manager factories have been set with 'createEntityManagerFactory'"); return null; diff --git a/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/BasicBean.java b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/BasicBean.java index 96cc38f2b..c89cc555b 100644 --- a/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/BasicBean.java +++ b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/BasicBean.java @@ -1,28 +1,70 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * BasicBean.java + * + * Copyright 2014 Johnathan Ingram (jingram@rogueware.org) + * + * 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.switchyard.component.test.mixins.entitymanager; import javax.enterprise.inject.Default; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; +import javax.persistence.Query; /** + * BasicBean * - * @author jingram + * @author rschamm */ @Default public class BasicBean { - - @PersistenceContext - private EntityManager em; - public EntityManager getEm() { - return em; - } - + @PersistenceContext + private EntityManager emOne; // should default to mixin-test-one + + @PersistenceContext(unitName = "mixin-test-two") + private EntityManager emTwo; + + public static final String ORIGINAL_NAME = "Peter"; + public static final String UPDATED_NAME_1 = "Peter!!!"; + public static final String UPDATED_NAME_2 = "Peter???"; + + public void testUpdate() throws Exception { + + try + { + // + // Using emOne + // + Query query = emOne.createQuery("update BasicTable set name = :name"); + query.setParameter("name", UPDATED_NAME_1); + query.executeUpdate(); + + // + // Using emTwo + // + query = emTwo.createQuery("update BasicTable set name = :name"); + query.setParameter("name", UPDATED_NAME_2); + query.executeUpdate(); + } + catch (Exception ex) + { + System.out.println("Failed to update name. Error:" + ex.getMessage()); + ex.printStackTrace(); + throw ex; + } + } - } diff --git a/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/BasicTable.java b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/BasicTable.java new file mode 100644 index 000000000..04fd7fe69 --- /dev/null +++ b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/BasicTable.java @@ -0,0 +1,120 @@ +/* + * BasicTable.java + * + * Copyright 2014 Johnathan Ingram (jingram@rogueware.org) + * + * 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.switchyard.component.test.mixins.entitymanager; + +import java.io.Serializable; +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +/** + * BasicTable + * + * @author rschamm + */ +@Entity +@Table(name = "BasicTable") +public class BasicTable implements Serializable { + + private static final long serialVersionUID = 1L; + @Id + @Basic(optional = false) + @NotNull + @Column(name = "id") + private Integer id; + @Basic(optional = false) + @NotNull + @Size(min = 1, max = 50) + @Column(name = "name") + private String name; + @Basic(optional = false) + @NotNull + @Size(min = 1, max = 100) + @Column(name = "description") + private String description; + + public BasicTable() { + } + + public BasicTable(Integer id) { + this.id = id; + } + + public BasicTable(Integer id, String name, String description) { + this.id = id; + this.name = name; + this.description = description; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public int hashCode() { + int hash = 0; + hash += (id != null ? id.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object object) { + // TODO: Warning - this method won't work in the case the id fields are not set + if (!(object instanceof BasicTable)) + { + return false; + } + BasicTable other = (BasicTable) object; + if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) + { + return false; + } + return true; + } + + @Override + public String toString() { + return "BasicTable[ id=" + id + " ]"; + } + +} diff --git a/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInSelfInjectTest.java b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInSelfInjectTest.java deleted file mode 100644 index 855f2ffac..000000000 --- a/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInSelfInjectTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Copyright 2014 Johnathan Ingram (jingram@rogueware.org) - * - * 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.switchyard.component.test.mixins.entitymanager; - -import javax.inject.Inject; -import static org.junit.Assert.assertNotNull; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.switchyard.component.test.mixins.cdi.CDIMixIn; -import org.switchyard.component.test.mixins.naming.NamingMixIn; -import org.switchyard.component.test.mixins.transaction.TransactionMixIn; -import org.switchyard.test.SwitchYardRunner; -import org.switchyard.test.SwitchYardTestCaseConfig; - -/** - * Unit test for {@link EntityManagerQMixIn}. - * - * @author Johnathan Ingram (jingram@rogueware.org) - * - */ -@RunWith(SwitchYardRunner.class) -@SwitchYardTestCaseConfig(mixins = {CDIMixIn.class, NamingMixIn.class, TransactionMixIn.class, EntityManagerMixIn.class}) -public class EntityManagerMixInSelfInjectTest { - - //private NamingMixIn namingMixIn; - //private TransactionMixIn transactionMixIn; - private EntityManagerMixIn entityManagerMixIn; - - @Inject - BasicBean tb; - - @Before - public void setup() throws Exception { - entityManagerMixIn.createEntityManagerFactory("mixin-test-one", "java:jboss/datasources/MixInTestOne", "org.h2.Driver", "jdbc:h2:mem:testDB-one", "sa", "sa"); - } - - @Test - public void getClientSession() { - assertNotNull("Entity Manager not injected", tb.getEm()); - } - -} diff --git a/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInTest.java b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInTest.java new file mode 100644 index 000000000..0017bb4bc --- /dev/null +++ b/test/mixins/entitymanager/src/test/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixInTest.java @@ -0,0 +1,160 @@ +/* + * EntityManagerMixInTest.java + * + * Copyright 2014 Johnathan Ingram (jingram@rogueware.org) + * + * 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.switchyard.component.test.mixins.entitymanager; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import javax.inject.Inject; +import org.junit.AfterClass; +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.switchyard.component.test.mixins.cdi.CDIMixIn; +import org.switchyard.component.test.mixins.naming.NamingMixIn; +import org.switchyard.component.test.mixins.transaction.TransactionMixIn; +import org.switchyard.test.SwitchYardRunner; +import org.switchyard.test.SwitchYardTestCaseConfig; + +/** + * EntityManagerMixInTest + * + * @author rschamm + */ +@RunWith(SwitchYardRunner.class) +@SwitchYardTestCaseConfig(mixins = +{ + CDIMixIn.class, NamingMixIn.class, TransactionMixIn.class, EntityManagerMixIn.class +}) +public class EntityManagerMixInTest { + + private TransactionMixIn transactionMixIn; + private EntityManagerMixIn entityManagerMixIn; + + private static final String persistenceUnitNameOne = "mixin-test-one"; + private static final String jtaDataSourceOne = "java:jboss/datasources/MixInTestOne"; + private static final String datasourceUrlOne = "jdbc:h2:mem:testDB-one"; + + private static final String persistenceUnitNameTwo = "mixin-test-two"; + private static final String jtaDataSourceTwo = "java:jboss/datasources/MixInTestTwo"; + private static final String datasourceUrlTwo = "jdbc:h2:mem:testDB-two"; + + private static final String datasourceDriverName = "org.h2.Driver"; + private static final String datasourceUser = "sa"; + private static final String dataSourcePassword = "sa"; + + private static Connection connectionOne; + private static Connection connectionTwo; + + @Inject + BasicBean basicBean; + + @BeforeClass + public static void setUp() throws Exception { + connectionOne = DriverManager.getConnection(datasourceUrlOne, datasourceUser, dataSourcePassword); + connectionTwo = DriverManager.getConnection(datasourceUrlTwo, datasourceUser, dataSourcePassword); + } + + @Before + public void setup() throws Exception { + // PU one + entityManagerMixIn.createEntityManagerFactory( + persistenceUnitNameOne, + jtaDataSourceOne, + datasourceDriverName, + datasourceUrlOne, + datasourceUser, + dataSourcePassword); + + // PU two + entityManagerMixIn.createEntityManagerFactory( + persistenceUnitNameTwo, + jtaDataSourceTwo, + datasourceDriverName, + datasourceUrlTwo, + datasourceUser, + dataSourcePassword); + + initSQL(connectionOne); + initSQL(connectionTwo); + } + + @AfterClass + public static void shutDown() throws SQLException { + cleanSQL(connectionOne); + cleanSQL(connectionTwo); + } + + @Test + public void testUpdateCommit() throws Exception { + assertEquals(BasicBean.ORIGINAL_NAME, getName(connectionOne)); + assertEquals(BasicBean.ORIGINAL_NAME, getName(connectionTwo)); + + transactionMixIn.getUserTransaction().begin(); + basicBean.testUpdate(); + transactionMixIn.getUserTransaction().commit(); + + assertEquals(BasicBean.UPDATED_NAME_1, getName(connectionOne)); + assertEquals(BasicBean.UPDATED_NAME_2, getName(connectionTwo)); + } + + @Test + public void testUpdateRollback() throws Exception { + assertEquals(BasicBean.ORIGINAL_NAME, getName(connectionOne)); + assertEquals(BasicBean.ORIGINAL_NAME, getName(connectionTwo)); + + transactionMixIn.getUserTransaction().begin(); + basicBean.testUpdate(); + transactionMixIn.getUserTransaction().rollback(); + + assertEquals(BasicBean.ORIGINAL_NAME, getName(connectionOne)); + assertEquals(BasicBean.ORIGINAL_NAME, getName(connectionTwo)); + } + + private String getName(Connection c) throws SQLException { + String name = null; + String sql = "SELECT name FROM BasicTable"; + Statement stmt = c.createStatement(); + ResultSet rs = stmt.executeQuery(sql); + if (rs.next()) + { + name = rs.getString("name"); + } + rs.close(); + stmt.close(); + return name; + } + + private void initSQL(Connection c) throws SQLException { + c.prepareStatement("DROP TABLE BasicTable IF EXISTS").execute(); + c.prepareStatement("CREATE TABLE BasicTable( ID BIGINT, NAME VARCHAR2(50), DESCRIPTION VARCHAR2(100))").execute(); + c.prepareStatement("INSERT INTO BasicTable (id, name, description) VALUES (1, '" + BasicBean.ORIGINAL_NAME + "', 'Description')").execute(); + } + + private static void cleanSQL(Connection c) throws SQLException { + if (!c.isClosed()) + { + c.close(); + } + } +} diff --git a/test/mixins/entitymanager/src/test/resources/META-INF/persistence.xml b/test/mixins/entitymanager/src/test/resources/META-INF/persistence.xml index b8bfccb2e..50cf33567 100644 --- a/test/mixins/entitymanager/src/test/resources/META-INF/persistence.xml +++ b/test/mixins/entitymanager/src/test/resources/META-INF/persistence.xml @@ -1,9 +1,25 @@ - - org.hibernate.ejb.HibernatePersistence - java:jboss/datasources/MixInTestOne - - - + + org.hibernate.ejb.HibernatePersistence + java:jboss/datasources/MixInTestOne + org.switchyard.component.test.mixins.entitymanager.BasicTable + true + + + + + + + + org.hibernate.ejb.HibernatePersistence + java:jboss/datasources/MixInTestTwo + org.switchyard.component.test.mixins.entitymanager.BasicTable + true + + + + + + From 1eb16eff7044dd1daf6bbd76220debb408df5372 Mon Sep 17 00:00:00 2001 From: Johnathan Ingram Date: Thu, 11 Dec 2014 17:05:43 +0200 Subject: [PATCH 6/7] SWITCHYARD-2474 Added dependency and super for Entity Manager MixIn --- .../test/mixins/entitymanager/EntityManagerMixIn.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java index 15931c5e7..15f0c5dd0 100644 --- a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java +++ b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java @@ -32,14 +32,17 @@ import org.enhydra.jdbc.standard.StandardXADataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.switchyard.component.test.mixins.cdi.CDIMixIn; import org.switchyard.component.test.mixins.naming.NamingMixIn; import org.switchyard.component.test.mixins.transaction.TransactionMixIn; +import org.switchyard.test.MixInDependencies; import org.switchyard.test.mixins.AbstractTestMixIn; /** * * @author Johnathan Ingram (jingram@rogueware.org) */ +@MixInDependencies(required = {CDIMixIn.class, NamingMixIn.class, TransactionMixIn.class}) public class EntityManagerMixIn extends AbstractTestMixIn { protected static final Logger log = LoggerFactory.getLogger(EntityManagerMixIn.class); @@ -51,6 +54,8 @@ public class EntityManagerMixIn extends AbstractTestMixIn { @Override public void initialize() { + super.initialize(); + // Get a reference to the TransactionMixIn try { transactionMixIn = getTestKit().getMixIn(TransactionMixIn.class); From 6290d4bb6890c10a6049cc42e20d582b6a0e2bf2 Mon Sep 17 00:00:00 2001 From: Johnathan Ingram Date: Thu, 11 Dec 2014 17:39:04 +0200 Subject: [PATCH 7/7] SWITCHYARD-2474 Cleaned up dependencies and removed Annotations class --- test/mixins/entitymanager/pom.xml | 32 +---- .../entitymanager/AnnotationWrappers.java | 117 ------------------ .../CDIPersistenceExtension.java | 16 ++- .../entitymanager/EntityManagerMixIn.java | 3 +- 4 files changed, 18 insertions(+), 150 deletions(-) delete mode 100644 test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/AnnotationWrappers.java diff --git a/test/mixins/entitymanager/pom.xml b/test/mixins/entitymanager/pom.xml index ef4dce61d..f137326c4 100644 --- a/test/mixins/entitymanager/pom.xml +++ b/test/mixins/entitymanager/pom.xml @@ -28,12 +28,6 @@ - - com.h2database - h2 - 1.4.181 - - com.experlog xapool @@ -44,18 +38,6 @@ - - - org.switchyard - switchyard-api - - - org.switchyard - switchyard-common - - - - com.h2database h2 @@ -72,6 +54,7 @@ + org.switchyard.components switchyard-component-test-mixin-cdi @@ -87,7 +70,6 @@ org.switchyard.components switchyard-component-bean - test @@ -101,18 +83,6 @@ - - org.jboss.spec.javax.resource - jboss-connector-api_1.6_spec - - - org.jboss.weld.se - weld-se-core - - - org.jboss.weld - weld-spi - com.experlog xapool diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/AnnotationWrappers.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/AnnotationWrappers.java deleted file mode 100644 index 49dd3166f..000000000 --- a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/AnnotationWrappers.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * AnnotationWrappers.java - * - * Copyright 2014 Johnathan Ingram (jingram@rogueware.org) - * - * 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.switchyard.component.test.mixins.entitymanager; - -import java.lang.annotation.Annotation; - -/** - * - * @author Johnathan Ingram (jingram@rogueware.org) - */ -public class AnnotationWrappers { - - private AnnotationWrappers() { - } - - public static class Inject { - - @javax.inject.Inject - public static Object field; - - public static Annotation getAnnotation() { - try { - return Inject.class.getField("field").getAnnotation(javax.inject.Inject.class); - } catch (Exception ex) { - return null; - } - } - } - - @javax.inject.Named - public static class Named { - - public static Annotation getAnnotation() { - try { - return Named.class.getAnnotation(javax.inject.Named.class); - } catch (Exception ex) { - return null; - } - } - } - - @javax.inject.Singleton - public static class Singleton { - - public static Annotation getAnnotation() { - try { - return Dependent.class.getAnnotation(javax.inject.Singleton.class); - } catch (Exception ex) { - return null; - } - } - } - - @javax.enterprise.context.Dependent - public static class Dependent { - - public static Annotation getAnnotation() { - try { - return Dependent.class.getAnnotation(javax.enterprise.context.Dependent.class); - } catch (Exception ex) { - return null; - } - } - } - - @javax.enterprise.context.RequestScoped - public static class RequestScoped { - - public static Annotation getAnnotation() { - try { - return RequestScoped.class.getAnnotation(javax.enterprise.context.RequestScoped.class); - } catch (Exception ex) { - return null; - } - } - } - - @javax.enterprise.context.ApplicationScoped - public static class ApplicationScoped { - - public static Annotation getAnnotation() { - try { - return ApplicationScoped.class.getAnnotation(javax.enterprise.context.ApplicationScoped.class); - } catch (Exception ex) { - return null; - } - } - } - - @javax.enterprise.inject.Default - public static class Default { - - public static Annotation getAnnotation() { - try { - return Default.class.getAnnotation(javax.enterprise.inject.Default.class); - } catch (Exception ex) { - return null; - } - } - } -} diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/CDIPersistenceExtension.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/CDIPersistenceExtension.java index 279f073e0..a891cd0eb 100644 --- a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/CDIPersistenceExtension.java +++ b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/CDIPersistenceExtension.java @@ -75,7 +75,7 @@ public Set> getFields() { // make sure the field has the @Inject if (javax.persistence.EntityManager.class.equals(af.getJavaMember().getType()) && af.isAnnotationPresent(PersistenceContext.class)) { - result.add(addAnnotation(af, AnnotationWrappers.Inject.getAnnotation())); + result.add(addAnnotation(af, Inject.getAnnotation())); } else { result.add(af); } @@ -172,4 +172,18 @@ public boolean isAnnotationPresent(Class annotationType) { } }; } + + public static class Inject { + + @javax.inject.Inject + public static Object field; + + public static Annotation getAnnotation() { + try { + return Inject.class.getField("field").getAnnotation(javax.inject.Inject.class); + } catch (Exception ex) { + return null; + } + } + } } diff --git a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java index 15f0c5dd0..d9605f869 100644 --- a/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java +++ b/test/mixins/entitymanager/src/main/java/org/switchyard/component/test/mixins/entitymanager/EntityManagerMixIn.java @@ -19,7 +19,6 @@ package org.switchyard.component.test.mixins.entitymanager; import java.util.Collections; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import javax.naming.InitialContext; @@ -151,4 +150,6 @@ protected static TransactionManager getTransactionManager() { return null; } } + + }