Liran Zelkha has uploaded a new change for review. Change subject: core: Infra for injecting beans in external JARs ......................................................................
core: Infra for injecting beans in external JARs This patch introduces a ModuleExtension that can inject beans that are not part of the EAR file. This is a limitation of JBoss 7, which is fixed in future versions. Once we stop supporting older jboss - this code can be safely removed Change-Id: I3b3c2c57178b5df4f98b4191ac9a06f9129414d0 Bug-Url: https://bugzilla.redhat.com/1159621 Signed-off-by: lzel...@redhat.com <lzel...@redhat.com> --- M backend/manager/dependencies/common/pom.xml A backend/manager/dependencies/common/src/main/modules/org/deltaspike/main/module.xml A backend/manager/dependencies/common/src/main/modules/org/reflections/main/module.xml M backend/manager/modules/bll/pom.xml M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/Injector.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/ModuleConfigurationExtension.java A backend/manager/modules/bll/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/SimpleDependecyInjector.java M backend/manager/modules/dal/src/main/modules/org/ovirt/engine/core/dal/main/module.xml D backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/CustomizedContextLoader.java A backend/manager/modules/dal/src/test/resources/test-beans.xml M ear/src/main/resources/META-INF/MANIFEST.MF M pom.xml 13 files changed, 226 insertions(+), 65 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/39/37439/1 diff --git a/backend/manager/dependencies/common/pom.xml b/backend/manager/dependencies/common/pom.xml index 87bd5b9..d4920bd 100644 --- a/backend/manager/dependencies/common/pom.xml +++ b/backend/manager/dependencies/common/pom.xml @@ -379,6 +379,24 @@ <version>${jackson.version}</version> </dependency> + <dependency> + <groupId>org.apache.deltaspike.core</groupId> + <artifactId>deltaspike-core-api</artifactId> + <version>${deltaspike.version}</version> + </dependency> + + <dependency> + <groupId>org.apache.deltaspike.core</groupId> + <artifactId>deltaspike-core-impl</artifactId> + <version>${deltaspike.version}</version> + </dependency> + + <dependency> + <groupId>org.reflections</groupId> + <artifactId>reflections</artifactId> + <version>${reflections.version}</version> + </dependency> + </dependencies> <build> @@ -734,6 +752,24 @@ <moduleName>org.codehaus.jackson.jackson-xc</moduleName> </module> + <module> + <groupId>org.apache.deltaspike.core</groupId> + <artifactId>deltaspike-core-api</artifactId> + <moduleName>org.deltaspike</moduleName> + </module> + + <module> + <groupId>org.apache.deltaspike.core</groupId> + <artifactId>deltaspike-core-impl</artifactId> + <moduleName>org.deltaspike</moduleName> + </module> + + <module> + <groupId>org.reflections</groupId> + <artifactId>reflections</artifactId> + <moduleName>org.reflections</moduleName> + </module> + </modules> </configuration> </plugin> diff --git a/backend/manager/dependencies/common/src/main/modules/org/deltaspike/main/module.xml b/backend/manager/dependencies/common/src/main/modules/org/deltaspike/main/module.xml new file mode 100644 index 0000000..323bb1e --- /dev/null +++ b/backend/manager/dependencies/common/src/main/modules/org/deltaspike/main/module.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<module xmlns="urn:jboss:module:1.1" name="org.deltaspike"> + + <resources> + <resource-root path="deltaspike-core-api.jar" /> + <resource-root path="deltaspike-core-impl.jar" /> + </resources> + + <dependencies> + <module name="com.google.guava" /> + <module name="javax.enterprise.api" /> + <module name="javax.inject.api" /> + </dependencies> +</module> diff --git a/backend/manager/dependencies/common/src/main/modules/org/reflections/main/module.xml b/backend/manager/dependencies/common/src/main/modules/org/reflections/main/module.xml new file mode 100644 index 0000000..88d66f9 --- /dev/null +++ b/backend/manager/dependencies/common/src/main/modules/org/reflections/main/module.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<module xmlns="urn:jboss:module:1.1" name="org.reflections"> + + <resources> + <resource-root path="reflections.jar" /> + </resources> + + <dependencies> + <module name="com.google.guava" /> + <module name="org.javassist" /> + <module name="org.slf4j" /> + </dependencies> +</module> diff --git a/backend/manager/modules/bll/pom.xml b/backend/manager/modules/bll/pom.xml index 6d70c82..240bf1d 100644 --- a/backend/manager/modules/bll/pom.xml +++ b/backend/manager/modules/bll/pom.xml @@ -163,6 +163,39 @@ <artifactId>cdi-api</artifactId> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.scala-lang</groupId> + <artifactId>scala-library</artifactId> + <version>2.10.4</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <version>1.1.4.RELEASE</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>javax.enterprise</groupId> + <artifactId>cdi-api</artifactId> + <version>1.0-SP4</version> + </dependency> + <dependency> + <groupId>org.apache.deltaspike.core</groupId> + <artifactId>deltaspike-core-api</artifactId> + <version>${deltaspike.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.deltaspike.core</groupId> + <artifactId>deltaspike-core-impl</artifactId> + <version>${deltaspike.version}</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>org.reflections</groupId> + <artifactId>reflections</artifactId> + <version>${reflections.version}</version> + </dependency> </dependencies> <build> diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/Injector.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/Injector.java index 1d06274..77fcf73 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/Injector.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/Injector.java @@ -8,9 +8,6 @@ import javax.inject.Inject; import javax.inject.Singleton; -import org.ovirt.engine.core.bll.CommandBase; -import org.ovirt.engine.core.common.action.VdcActionParametersBase; - /** * an application wide interaction point with the CDI container mostly to gap all the existing unmanged code * or for unmanaged code which wants interaction with managed beans. @@ -38,7 +35,7 @@ * @param <T> an unmanaged CDI instance with some members containing <code>@Inject</code> annotated * members */ - public static <T extends CommandBase<? extends VdcActionParametersBase>> T injectMembers(T instance) { + public static <T> T injectMembers(T instance) { AnnotatedType type = injector.manager.createAnnotatedType(instance.getClass()); InjectionTarget injectionTarget = injector.manager.createInjectionTarget(type); injectionTarget.inject(instance, injector.manager.createCreationalContext(null)); diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/ModuleConfigurationExtension.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/ModuleConfigurationExtension.java new file mode 100644 index 0000000..42d6445 --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/ModuleConfigurationExtension.java @@ -0,0 +1,97 @@ +package org.ovirt.engine.core.bll.utils; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import javax.enterprise.event.Observes; +import javax.enterprise.inject.Any; +import javax.enterprise.inject.spi.AfterBeanDiscovery; +import javax.enterprise.inject.spi.AnnotatedType; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.BeforeBeanDiscovery; +import javax.enterprise.inject.spi.Extension; +import javax.enterprise.util.AnnotationLiteral; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.apache.deltaspike.core.util.bean.BeanBuilder; +import org.apache.deltaspike.core.util.metadata.builder.AnnotatedTypeBuilder; +import org.reflections.Reflections; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Strings; + +public class ModuleConfigurationExtension implements Extension { + private static final Logger log = LoggerFactory.getLogger(ModuleConfigurationExtension.class); + private final Map<String, AnnotatedType<Object>> beans = new HashMap<>(); + + /** + * This method is automatically activated by CDI, and loads all classes in the org.ovirt package that has NAMED or + * SINGLETON annotations. + * @param bdd + */ + void readAllConfigurations(final @Observes BeforeBeanDiscovery bdd, BeanManager bm) { + log.info("Starting to load beans from modules"); + addBeansFromPackage(bdd, bm, "org.ovirt.engine.core.dal"); + addBeansFromPackage(bdd, bm, "org.ovirt.engine.core.dao"); + } + + private void addBeansFromPackage(final BeforeBeanDiscovery bdd, BeanManager bm, String packageName) { + Reflections reflections = new Reflections(packageName); + Set<Class<?>> beanClasses = reflections.getTypesAnnotatedWith(Named.class); + beanClasses.addAll(reflections.getTypesAnnotatedWith(Singleton.class)); + + for (Class<?> bean : beanClasses) { + @SuppressWarnings({ "unchecked", "rawtypes" }) + AnnotatedType<Object> annotatedType = new AnnotatedTypeBuilder().readFromType(bean).create(); + Set<Bean<?>> foundBeans = bm.getBeans(annotatedType.getBaseType(), new AnnotationLiteral<Any>() { + }); + + if (foundBeans.size() == 0) { + bdd.addAnnotatedType(annotatedType); + String name; + Named named = bean.getAnnotation(Named.class); + if (named == null || Strings.isNullOrEmpty(named.value())) { + name = bean.getSimpleName(); + } else { + name = named.value(); + } + beans.put(name, annotatedType); + } + } + } + + /** + * This method actually initializes the beans we discovered in <code>readAllConfigurations</code>. Again - this + * method is automatically activated by CDI + * @param abd + * @param bm + * @throws Exception + */ + public void addCdiBeans(final @Observes AfterBeanDiscovery abd, final BeanManager bm) throws Exception { + log.info("Starting to initialize beans from modules"); + + for (Map.Entry<String, AnnotatedType<Object>> bean : beans.entrySet()) { + Set<Bean<?>> foundBeans = bm.getBeans(bean.getValue().getBaseType()); + if (foundBeans.size() == 0) { + final Bean<Object> cdiBean = createBean(bm, bean.getKey(), bean.getValue()); + abd.addBean(cdiBean); + log.debug("Added bean " + cdiBean.getName()); + } + } + } + + private static Bean<Object> createBean(final BeanManager bm, + final String name, + final AnnotatedType<Object> annotatedType) + throws Exception { + final BeanBuilder<Object> beanBuilder = new BeanBuilder<Object>(bm). + readFromType(annotatedType). + name(name); + + return beanBuilder.create(); + } +} diff --git a/backend/manager/modules/bll/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/backend/manager/modules/bll/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension new file mode 100644 index 0000000..2184d5b --- /dev/null +++ b/backend/manager/modules/bll/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension @@ -0,0 +1 @@ +org.ovirt.engine.core.bll.utils.ModuleConfigurationExtension \ No newline at end of file diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/SimpleDependecyInjector.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/SimpleDependecyInjector.java index 03ba93c..85da37a 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/SimpleDependecyInjector.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/SimpleDependecyInjector.java @@ -63,6 +63,7 @@ * @param <T> * @return */ + @SuppressWarnings("unchecked") public <T> T get(Class<T> clazz) { return (T) map.get(clazz.getName()); } diff --git a/backend/manager/modules/dal/src/main/modules/org/ovirt/engine/core/dal/main/module.xml b/backend/manager/modules/dal/src/main/modules/org/ovirt/engine/core/dal/main/module.xml index 43f6a82..8115488 100644 --- a/backend/manager/modules/dal/src/main/modules/org/ovirt/engine/core/dal/main/module.xml +++ b/backend/manager/modules/dal/src/main/modules/org/ovirt/engine/core/dal/main/module.xml @@ -7,7 +7,9 @@ </resources> <dependencies> + <module name="javax.annotation.api"/> <module name="javax.api"/> + <module name="javax.inject.api"/> <module name="javax.transaction.api"/> <module name="org.apache.commons.collections"/> <module name="org.apache.commons.lang"/> diff --git a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/CustomizedContextLoader.java b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/CustomizedContextLoader.java deleted file mode 100644 index 3a1a830..0000000 --- a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/CustomizedContextLoader.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.ovirt.engine.core.dao; - -import javax.sql.DataSource; - -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.test.context.MergedContextConfiguration; -import org.springframework.test.context.support.AbstractContextLoader; - -/** - * This class is used to provide load the application context for the spring framework in a custom way. The - * customization is for providing the transaction manager that is using the data source from the BaseDAOTestCase. - * - */ -public class CustomizedContextLoader extends AbstractContextLoader { - - @Override - protected String getResourceSuffix() { - return "dummy"; - } - - @Override - public ApplicationContext loadContext(String ... locations) throws Exception { - return doLoadContext(); - } - - @Override - public ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception { - return doLoadContext(); - } - - private ApplicationContext doLoadContext() throws Exception { - // initialize spring application context to enable transaction support within - // the Spring TestContext Framework - GenericApplicationContext ctx = new GenericApplicationContext() { - @SuppressWarnings("unchecked") - @Override - public Object getBean(String name, Class requiredType) throws BeansException { - if ("transactionManager".equals(name)) { - DataSource dataSource = BaseDAOTestCase.getDataSource(); - if (dataSource != null) { - DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource); - transactionManager.afterPropertiesSet(); - return transactionManager; - } - else { - System.err.println("loading context for transaction management but data source is not initializaed yet. " - + - "Please make sure datasource is initializaed in BaseDAOTestCase before loading the test context."); - throw new IllegalStateException("datasource is not initializaed"); - } - } - return super.getBean(name, requiredType); - } - }; - return ctx; - } -} diff --git a/backend/manager/modules/dal/src/test/resources/test-beans.xml b/backend/manager/modules/dal/src/test/resources/test-beans.xml new file mode 100644 index 0000000..f490b71 --- /dev/null +++ b/backend/manager/modules/dal/src/test/resources/test-beans.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" + xmlns:context="http://www.springframework.org/schema/context" + + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context.xsd"> + + <context:component-scan base-package="org.ovirt.engine" /> + <context:annotation-config /> + + <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> + <constructor-arg ref="DataSource"/> + </bean> + <bean id="DataSource" class="org.ovirt.engine.core.dao.BaseDAOTestCase" factory-method="getDataSource" /> +</beans> \ No newline at end of file diff --git a/ear/src/main/resources/META-INF/MANIFEST.MF b/ear/src/main/resources/META-INF/MANIFEST.MF index 3f34aed..16c4496 100644 --- a/ear/src/main/resources/META-INF/MANIFEST.MF +++ b/ear/src/main/resources/META-INF/MANIFEST.MF @@ -1,5 +1,6 @@ Manifest-Version: 1.0 Dependencies: asm.asm, + com.google.guava, javax.validation.api, org.apache.commons.beanutils, org.apache.commons.codec, @@ -10,12 +11,13 @@ org.apache.xmlrpc, org.codehaus.jackson.jackson-core-asl, org.codehaus.jackson.jackson-mapper-asl, + org.deltaspike, org.dom4j, org.hibernate.validator, org.infinispan, org.ovirt.engine.core.common, org.ovirt.engine.core.compat, - org.ovirt.engine.core.dal, + org.ovirt.engine.core.dal meta-inf, org.ovirt.engine.core.searchbackend, org.ovirt.engine.core.utils, org.ovirt.engine.core.uutils, @@ -27,6 +29,7 @@ org.ovirt.engine.api.ovirt-engine-extensions-api, org.ovirt.vdsm-jsonrpc-java, org.quartz, + org.reflections, org.slf4j, org.springframework, com.woorea.openstack.sdk services, diff --git a/pom.xml b/pom.xml index 8350ea5..aa593fb 100644 --- a/pom.xml +++ b/pom.xml @@ -110,6 +110,9 @@ <gwt-maven-plugin.workingRefresh.version>2.4.0</gwt-maven-plugin.workingRefresh.version> <cdi.api.version>1.0-SP4</cdi.api.version> <javacc.version>2.6</javacc.version> + <antlr.version>4.2.2</antlr.version> + <deltaspike.version>1.1.0</deltaspike.version> + <reflections.version>0.9.9-RC1</reflections.version> </properties> <dependencyManagement> <dependencies> -- To view, visit http://gerrit.ovirt.org/37439 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I3b3c2c57178b5df4f98b4191ac9a06f9129414d0 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Liran Zelkha <lzel...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches