Author: ggerla Date: Sun Jul 5 08:00:47 2015 New Revision: 1689222 URL: http://svn.apache.org/r1689222 Log: - Implemented ARIES-1345 scanning all jpa annotated methods - Add integration test to verify new functionality
Added: aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/itest/testbundle/service/impl/CarServiceWithMethodImpl.java aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/itest/testbundle/service/impl/CarServiceWithMultiAnnotationImpl.java aries/trunk/jpa/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/blueprint/aries/itest/BlueprintWithMethodTest.java Modified: aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml aries/trunk/jpa/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaBeanProcessor.java Added: aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/itest/testbundle/service/impl/CarServiceWithMethodImpl.java URL: http://svn.apache.org/viewvc/aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/itest/testbundle/service/impl/CarServiceWithMethodImpl.java?rev=1689222&view=auto ============================================================================== --- aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/itest/testbundle/service/impl/CarServiceWithMethodImpl.java (added) +++ aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/itest/testbundle/service/impl/CarServiceWithMethodImpl.java Sun Jul 5 08:00:47 2015 @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 WARRANTIESOR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.aries.jpa.itest.testbundle.service.impl; + +import java.util.Collection; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.apache.aries.jpa.itest.testbundle.entities.Car; +import org.apache.aries.jpa.itest.testbundle.service.CarService; + + +public class CarServiceWithMethodImpl implements CarService { + + EntityManager em; + + @Override + public Car getCar(String id) { + return em.find(Car.class, id); + } + + @Override + public void addCar(Car car) { + em.persist(car); + em.flush(); + } + + public Collection<Car> getCars() { + return em.createQuery("select c from Car c", Car.class) + .getResultList(); + } + + @Override + public void updateCar(Car car) { + em.persist(car); + } + + @Override + public void deleteCar(String id) { + em.remove(getCar(id)); + } + + @PersistenceContext(unitName="test_unit_blueprint") + public void setEm(EntityManager em) { + this.em = em; + } + +} Added: aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/itest/testbundle/service/impl/CarServiceWithMultiAnnotationImpl.java URL: http://svn.apache.org/viewvc/aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/itest/testbundle/service/impl/CarServiceWithMultiAnnotationImpl.java?rev=1689222&view=auto ============================================================================== --- aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/itest/testbundle/service/impl/CarServiceWithMultiAnnotationImpl.java (added) +++ aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/itest/testbundle/service/impl/CarServiceWithMultiAnnotationImpl.java Sun Jul 5 08:00:47 2015 @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 WARRANTIESOR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.aries.jpa.itest.testbundle.service.impl; + +import java.util.Collection; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.PersistenceContext; +import javax.persistence.PersistenceUnit; + +import org.apache.aries.jpa.itest.testbundle.entities.Car; +import org.apache.aries.jpa.itest.testbundle.service.CarService; +import org.apache.aries.jpa.supplier.EmSupplier; + + +public class CarServiceWithMultiAnnotationImpl implements CarService { + + @PersistenceContext(unitName="test_unit_blueprint") + EntityManager em; + + @PersistenceUnit(unitName="test_unit_blueprint") + EntityManagerFactory emf; + + @PersistenceContext(unitName="test_unit_blueprint") + EmSupplier ems; + + @Override + public Car getCar(String id) { + return em.find(Car.class, id); + } + + @Override + public void addCar(Car car) { + EntityManager localEm = emf.createEntityManager(); + localEm.persist(car); + localEm.flush(); + localEm.close(); + } + + public Collection<Car> getCars() { + return em.createQuery("select c from Car c", Car.class) + .getResultList(); + } + + @Override + public void updateCar(Car car) { + em.persist(car); + } + + @Override + public void deleteCar(String id) { + ems.get().remove(getCar(id)); + } + + public void setEm(EntityManager em) { + this.em = em; + } + + public void setEmf(EntityManagerFactory emf) { + this.emf = emf; + } + + public void setEms(EmSupplier ems) { + this.ems = ems; + } +} Modified: aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml URL: http://svn.apache.org/viewvc/aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml?rev=1689222&r1=1689221&r2=1689222&view=diff ============================================================================== --- aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml (original) +++ aries/trunk/jpa/itests/jpa-container-blueprint-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml Sun Jul 5 08:00:47 2015 @@ -54,6 +54,18 @@ class="org.apache.aries.jpa.itest.testbundle.service.impl.CarServiceWithMultiAnnotationImpl"> <tx:transaction method="*" value="Required" /> </bean> + + <service ref="carServiceMethod" + interface="org.apache.aries.jpa.itest.testbundle.service.CarService"> + <service-properties> + <entry key="type" value="method" /> + </service-properties> + </service> + + <bean id="carServiceMethod" + class="org.apache.aries.jpa.itest.testbundle.service.impl.CarServiceWithMethodImpl"> + <tx:transaction method="*" value="Required" /> + </bean> </blueprint> Added: aries/trunk/jpa/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/blueprint/aries/itest/BlueprintWithMethodTest.java URL: http://svn.apache.org/viewvc/aries/trunk/jpa/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/blueprint/aries/itest/BlueprintWithMethodTest.java?rev=1689222&view=auto ============================================================================== --- aries/trunk/jpa/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/blueprint/aries/itest/BlueprintWithMethodTest.java (added) +++ aries/trunk/jpa/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/blueprint/aries/itest/BlueprintWithMethodTest.java Sun Jul 5 08:00:47 2015 @@ -0,0 +1,56 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.aries.jpa.blueprint.aries.itest; + +import org.apache.aries.jpa.itest.AbstractJPAItest; +import org.apache.aries.jpa.itest.testbundle.entities.Car; +import org.apache.aries.jpa.itest.testbundle.service.CarService; +import org.junit.Assert; +import org.junit.Test; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; + +public class BlueprintWithMethodTest extends AbstractJPAItest { + + @Test + public void testEmfAddQuery() throws Exception { + CarService carService = getService(CarService.class, "(type=method)"); + + resolveBundles(); + Car c = new Car(); + c.setColour("Blue"); + c.setNumberPlate("AB11EMF"); + c.setNumberOfSeats(7); + c.setEngineSize(1900); + + carService.addCar(c); + + Car car2 = carService.getCar("AB11EMF"); + Assert.assertEquals(c.getNumberPlate(), car2.getNumberPlate()); + } + + @Configuration + public Option[] configuration() { + return new Option[] { + baseOptions(), // + ariesJpa20(), // + hibernate(), // + derbyDSF(), // + testBundleBlueprint(), + //debug() + }; + } +} Modified: aries/trunk/jpa/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaBeanProcessor.java URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaBeanProcessor.java?rev=1689222&r1=1689221&r2=1689222&view=diff ============================================================================== --- aries/trunk/jpa/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaBeanProcessor.java (original) +++ aries/trunk/jpa/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaBeanProcessor.java Sun Jul 5 08:00:47 2015 @@ -19,6 +19,7 @@ package org.apache.aries.jpa.blueprint.impl; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -80,14 +81,110 @@ public class JpaBeanProcessor implements public Object beforeInit(Object bean, String beanName, BeanCreator beanCreator, BeanMetadata beanData) { + managePersistenceFields(bean, beanName, beanCreator, beanData); + managePersistenceMethods(bean, beanName, beanCreator, beanData); + return bean; + } + + private Object getEmfProxy(Class<?> clazz, EntityManagerFactory supplierProxy) { + if (clazz == EntityManagerFactory.class) { + return supplierProxy; + } else { + throw new IllegalStateException( + "Field or setter Mthod with @PersistenceUnit has class not supported " + + clazz); + } + } + + private Object getEmProxy(Class<?> clazz, EmSupplierProxy supplierProxy) { + if (clazz == EmSupplier.class) { + return supplierProxy; + } else if (clazz == EntityManager.class) { + return EmProxyFactory.create(supplierProxy); + } else { + throw new IllegalStateException( + "Field or setter Method with @PersistenceContext has class not supported " + + clazz.getName()); + } + } + + private void managePersistenceMethods(Object bean, String beanName, + BeanCreator beanCreator, BeanMetadata beanData) { + Class<?> c = bean.getClass(); - List<Field> jpaAnnotated = new ArrayList<Field>(); - getPersistenceFields(c, jpaAnnotated); + List<Method> jpaAnnotated = getPersistenceMethods(c); - for (Field field : jpaAnnotated) { - if (field == null) { - return bean; + for (Method method : jpaAnnotated) { + BundleContext context = FrameworkUtil.getBundle(c) + .getBundleContext(); + method.setAccessible(true); + + PersistenceContext pcAnn = method + .getAnnotation(PersistenceContext.class); + if (pcAnn != null) { + LOGGER.debug( + "Adding jpa/jta interceptor bean {} with class {}", + beanName, c); + + EmSupplierProxy supplierProxy = new EmSupplierProxy(context, + pcAnn.unitName()); + emProxies.put(bean, supplierProxy); + try { + method.invoke(bean, getEmProxy(method.getParameterTypes()[0], supplierProxy)); + } catch (Exception e) { + throw new IllegalStateException("Error invoking method " + + method, e); + } + Interceptor interceptor = new JpaInterceptor(supplierProxy); + cdr.registerInterceptorWithComponent(beanData, interceptor); + } else { + PersistenceUnit puAnn = method + .getAnnotation(PersistenceUnit.class); + if (puAnn != null) { + LOGGER.debug("Adding emf proxy"); + + EntityManagerFactory emfProxy = EmfProxyFactory.create( + context, puAnn.unitName()); + emfProxies.put(bean, emfProxy); + try { + method.invoke(bean, getEmfProxy(method.getParameterTypes()[0], emfProxy)); + } catch (Exception e) { + throw new IllegalStateException("Error invoking method " + + method, e); + } + } } + } + } + + private List<Method> getPersistenceMethods(Class<?> c) { + List<Method> jpaAnnotated = new ArrayList<Method>(); + + List<Class<?>> managedJpaClasses = new ArrayList<Class<?>>(); + managedJpaClasses.add(EntityManagerFactory.class); + managedJpaClasses.add(EntityManager.class); + managedJpaClasses.add(EmSupplier.class); + + for (Method method : c.getDeclaredMethods()) { + if (method.getAnnotation(PersistenceContext.class) != null + || method.getAnnotation(PersistenceUnit.class) != null) { + + Class<?>[] pType = method.getParameterTypes(); + if (method.getName().startsWith("set") && pType.length == 1 + && managedJpaClasses.contains(pType[0])) { + jpaAnnotated.add(method); + } + } + } + return jpaAnnotated; + } + + private void managePersistenceFields(Object bean, String beanName, + BeanCreator beanCreator, BeanMetadata beanData) { + Class<?> c = bean.getClass(); + List<Field> jpaAnnotated = getPersistenceFields(c); + + for (Field field : jpaAnnotated) { BundleContext context = FrameworkUtil.getBundle(c) .getBundleContext(); field.setAccessible(true); @@ -103,7 +200,7 @@ public class JpaBeanProcessor implements pcAnn.unitName()); emProxies.put(bean, supplierProxy); try { - field.set(bean, getEmProxy(field, supplierProxy)); + field.set(bean, getEmProxy(field.getType(), supplierProxy)); } catch (Exception e) { throw new IllegalStateException("Error setting field " + field, e); @@ -120,7 +217,7 @@ public class JpaBeanProcessor implements context, puAnn.unitName()); emfProxies.put(bean, emfProxy); try { - field.set(bean, getEmfProxy(field, emfProxy)); + field.set(bean, getEmfProxy(field.getType(), emfProxy)); } catch (Exception e) { throw new IllegalStateException("Error setting field " + field, e); @@ -128,40 +225,18 @@ public class JpaBeanProcessor implements } } } - return bean; } - private Object getEmfProxy(Field field, EntityManagerFactory supplierProxy) { - if (field.getType() == EntityManagerFactory.class) { - return supplierProxy; - } else { - throw new IllegalStateException( - "Field with @PersistenceUnit is not of type EntityManagerFactory " - + field); - } - } - - private Object getEmProxy(Field field, EmSupplierProxy supplierProxy) { - if (field.getType() == EmSupplier.class) { - return supplierProxy; - } else if (field.getType() == EntityManager.class) { - return EmProxyFactory.create(supplierProxy); - } else { - throw new IllegalStateException( - "Field with @PersistenceContext is not of type EntityManager or EmSupplier " - + field); - } - } + private List<Field> getPersistenceFields(Class<?> c) { + List<Field> jpaAnnotated = new ArrayList<Field>(); - private void getPersistenceFields(Class<?> c, List<Field> jpaAnnotated) { for (Field field : c.getDeclaredFields()) { if (field.getAnnotation(PersistenceContext.class) != null || field.getAnnotation(PersistenceUnit.class) != null) { - if (jpaAnnotated != null) { - jpaAnnotated.add(field); - } + jpaAnnotated.add(field); } } + return jpaAnnotated; } }