From cbb032a4e384ae54d9c7f5f42758622f53a17bb7 Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Wed, 14 Jul 2010 19:54:22 +0000 Subject: [PATCH] cdi project in initial revision testing and docs to be added. --- support/cdi/.classpath | 9 +++ support/cdi/.project | 23 +++++++ .../cdi/.settings/org.eclipse.jdt.core.prefs | 6 ++ .../cdi/.settings/org.maven.ide.eclipse.prefs | 9 +++ support/cdi/TODO.txt | 6 ++ support/cdi/pom.xml | 38 ++++++++++ .../org/wamblee/cdi/BeanManagerLookup.java | 69 +++++++++++++++++++ .../java/org/wamblee/cdi/CdiInjector.java | 65 +++++++++++++++++ .../org/wamblee/cdi/CdiInjectorFactory.java | 66 ++++++++++++++++++ .../main/java/org/wamblee/cdi/Injectable.java | 36 ++++++++++ .../main/java/org/wamblee/cdi/Injector.java | 33 +++++++++ .../java/org/wamblee/cdi/InjectorCache.java | 67 ++++++++++++++++++ .../java/org/wamblee/cdi/InjectorFactory.java | 27 ++++++++ .../java/org/wamblee/cdi/SimpleInjector.java | 48 +++++++++++++ .../src/test/java/org/wamblee/cdi/MyPojo.java | 17 +++++ .../java/org/wamblee/cdi/MySingleton.java | 19 +++++ .../test/java/org/wamblee/cdi/WeldTest.java | 55 +++++++++++++++ .../cdi/src/test/resources/META-INF/beans.xml | 5 ++ support/general/pom.xml | 2 +- support/pom.xml | 1 + 20 files changed, 600 insertions(+), 1 deletion(-) create mode 100644 support/cdi/.classpath create mode 100644 support/cdi/.project create mode 100644 support/cdi/.settings/org.eclipse.jdt.core.prefs create mode 100644 support/cdi/.settings/org.maven.ide.eclipse.prefs create mode 100644 support/cdi/TODO.txt create mode 100644 support/cdi/pom.xml create mode 100644 support/cdi/src/main/java/org/wamblee/cdi/BeanManagerLookup.java create mode 100644 support/cdi/src/main/java/org/wamblee/cdi/CdiInjector.java create mode 100644 support/cdi/src/main/java/org/wamblee/cdi/CdiInjectorFactory.java create mode 100644 support/cdi/src/main/java/org/wamblee/cdi/Injectable.java create mode 100644 support/cdi/src/main/java/org/wamblee/cdi/Injector.java create mode 100644 support/cdi/src/main/java/org/wamblee/cdi/InjectorCache.java create mode 100644 support/cdi/src/main/java/org/wamblee/cdi/InjectorFactory.java create mode 100644 support/cdi/src/main/java/org/wamblee/cdi/SimpleInjector.java create mode 100644 support/cdi/src/test/java/org/wamblee/cdi/MyPojo.java create mode 100644 support/cdi/src/test/java/org/wamblee/cdi/MySingleton.java create mode 100644 support/cdi/src/test/java/org/wamblee/cdi/WeldTest.java create mode 100644 support/cdi/src/test/resources/META-INF/beans.xml diff --git a/support/cdi/.classpath b/support/cdi/.classpath new file mode 100644 index 00000000..6eaa0fea --- /dev/null +++ b/support/cdi/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/support/cdi/.project b/support/cdi/.project new file mode 100644 index 00000000..b0870aa2 --- /dev/null +++ b/support/cdi/.project @@ -0,0 +1,23 @@ + + + wamblee-support-cdi + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.maven.ide.eclipse.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.maven.ide.eclipse.maven2Nature + + diff --git a/support/cdi/.settings/org.eclipse.jdt.core.prefs b/support/cdi/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..dda55440 --- /dev/null +++ b/support/cdi/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,6 @@ +#Wed Jul 14 20:45:46 CEST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/support/cdi/.settings/org.maven.ide.eclipse.prefs b/support/cdi/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 00000000..38db0437 --- /dev/null +++ b/support/cdi/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Wed Jul 14 20:45:45 CEST 2010 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/support/cdi/TODO.txt b/support/cdi/TODO.txt new file mode 100644 index 00000000..d9a6915d --- /dev/null +++ b/support/cdi/TODO.txt @@ -0,0 +1,6 @@ + +* move maven dependency version to root pom +* add test code for complete behavior. +* setup site +* integrate with wamblee-utils. + diff --git a/support/cdi/pom.xml b/support/cdi/pom.xml new file mode 100644 index 00000000..e05b96c0 --- /dev/null +++ b/support/cdi/pom.xml @@ -0,0 +1,38 @@ + + + + + org.wamblee + wamblee-utils + 0.2.5-SNAPSHOT + + + 4.0.0 + org.wamblee + wamblee-support-cdi + jar + /support/cdi + http://wamblee.org + + + org.jboss.weld + weld-se + 1.0.1-Final + + + + + + + + + + support-cdi + file:${distrib}/support/cdi + + + + diff --git a/support/cdi/src/main/java/org/wamblee/cdi/BeanManagerLookup.java b/support/cdi/src/main/java/org/wamblee/cdi/BeanManagerLookup.java new file mode 100644 index 00000000..29526538 --- /dev/null +++ b/support/cdi/src/main/java/org/wamblee/cdi/BeanManagerLookup.java @@ -0,0 +1,69 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.cdi; + +import java.util.logging.Logger; + +import javax.enterprise.inject.spi.BeanManager; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +/** + * Class that encapsulates beanmanager lookup in a way so that the lookup can be + * explicitly overriden (e.g. for unit test). + * + * In case no bean manager is found the beanmanager is set to null and the + * problem is logged. + * + * @author Erik Brakkee + */ +public class BeanManagerLookup { + + private static final Logger LOGGER = Logger + .getLogger(BeanManagerLookup.class.getName()); + + private static final String BEAN_MANAGER_JNDI = "java:comp/BeanManager"; + private static BeanManager mgr = null; + + /** + * Sets the bean manager (mainly for testability). + * + * @param aMgr + * Bean manager. + */ + public static void setBeanManager(BeanManager aMgr) { + mgr = aMgr; + } + + /** + * Looks up the bean manager if not already cached and returns it. + * + * @return Bean manager. + */ + public static BeanManager lookup() { + if (mgr == null) { + try { + InitialContext ctx = new InitialContext(); + mgr = (BeanManager) ctx.lookup(BEAN_MANAGER_JNDI); + LOGGER.info("Beanmanager successfully located"); + } catch (NamingException e) { + LOGGER.warning("No beanmanager was found, using null"); + mgr = null; + } + } + return mgr; + } +} diff --git a/support/cdi/src/main/java/org/wamblee/cdi/CdiInjector.java b/support/cdi/src/main/java/org/wamblee/cdi/CdiInjector.java new file mode 100644 index 00000000..46d434b4 --- /dev/null +++ b/support/cdi/src/main/java/org/wamblee/cdi/CdiInjector.java @@ -0,0 +1,65 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.cdi; + +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.AnnotatedType; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.InjectionTarget; + +/** + * Class encapsulating bean injection into a specific non-contextual object of a + * given class. + * + * @author Erik Brakkee + */ +public class CdiInjector implements Injector { + private Class clazz; + private InjectionTarget target; + private CreationalContext ctx; + + /** + * Constructs the injector. + * + * @param aMgr + * Bean manager. + * @param aClass + * Class to analyse for injection. + */ + public CdiInjector(BeanManager aMgr, Class aClass) { + clazz = aClass; + AnnotatedType type = aMgr.createAnnotatedType(aClass); + target = aMgr.createInjectionTarget(type); + ctx = aMgr.createCreationalContext(null); + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.cdi.Injector#inject(java.lang.Object) + */ + public void inject(Object aComponent) { + if (aComponent != null) { + if (!clazz.isInstance(aComponent)) { + throw new RuntimeException("Object '" + aComponent + + "' is of type " + aComponent.getClass().getName() + + " but expected " + clazz.getName()); + } + target.inject(aComponent, ctx); + } + } + +} \ No newline at end of file diff --git a/support/cdi/src/main/java/org/wamblee/cdi/CdiInjectorFactory.java b/support/cdi/src/main/java/org/wamblee/cdi/CdiInjectorFactory.java new file mode 100644 index 00000000..74d1a669 --- /dev/null +++ b/support/cdi/src/main/java/org/wamblee/cdi/CdiInjectorFactory.java @@ -0,0 +1,66 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.cdi; + +import java.util.logging.Logger; + +import javax.enterprise.inject.spi.BeanManager; + +/** + * Factory that creates CDI injectors. In case no beanmanager is found then + * injectors will do nothing. This class may be subclassed for testing to + * override the injectors that are returned. + * + * @author Erik Brakkee + */ +public class CdiInjectorFactory implements InjectorFactory { + + private static final Logger LOGGER = Logger + .getLogger(CdiInjectorFactory.class.getName()); + + private BeanManager beanManager; + + /** + * Constructs the factory using the default bean manager. + */ + public CdiInjectorFactory() { + this(BeanManagerLookup.lookup()); + } + + /** + * Constructs the factory using an explicit bean manager. + * + * @param aBeanManager + */ + public CdiInjectorFactory(BeanManager aBeanManager) { + beanManager = aBeanManager; + } + + @Override + public Injector create(Class aClass) { + if (beanManager == null) { + // Typically for unit test. + return new Injector() { + @Override + public void inject(Object aComponent) { + // Empty. + } + }; + } + return new CdiInjector(beanManager, aClass); + } + +} diff --git a/support/cdi/src/main/java/org/wamblee/cdi/Injectable.java b/support/cdi/src/main/java/org/wamblee/cdi/Injectable.java new file mode 100644 index 00000000..6e9f7b8c --- /dev/null +++ b/support/cdi/src/main/java/org/wamblee/cdi/Injectable.java @@ -0,0 +1,36 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.cdi; + +/** + * This abstract base class performs injection at construction. + * Be sure not to initialize fields of derived classes to null as these will override the initializations + * of this base class. + * + * Use this by subclassing through + * {@link #Injectable()). + * + * @author Erik Brakkee + */ +public abstract class Injectable { + + /** + * Inheritance style constructor. + */ + protected Injectable() { + SimpleInjector.inject(this); + } +} diff --git a/support/cdi/src/main/java/org/wamblee/cdi/Injector.java b/support/cdi/src/main/java/org/wamblee/cdi/Injector.java new file mode 100644 index 00000000..ad1648e8 --- /dev/null +++ b/support/cdi/src/main/java/org/wamblee/cdi/Injector.java @@ -0,0 +1,33 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.cdi; + +/** + * Interface used to perform injection with. + * + * @author Erik Brakkee + */ +public interface Injector { + + /** + * Injects beans into a given component of the required class. + * + * @param aComponent + * Component to inject into. + */ + public abstract void inject(Object aComponent); + +} \ No newline at end of file diff --git a/support/cdi/src/main/java/org/wamblee/cdi/InjectorCache.java b/support/cdi/src/main/java/org/wamblee/cdi/InjectorCache.java new file mode 100644 index 00000000..69595c6e --- /dev/null +++ b/support/cdi/src/main/java/org/wamblee/cdi/InjectorCache.java @@ -0,0 +1,67 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.cdi; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Cache of {@link CdiInjector}s for efficiency to avoid duplicate analysis of a + * given class. + * + * @author Erik Brakkee + */ +public class InjectorCache { + + private Map injectors; + + private InjectorFactory injectorFactory; + + /** + * Constructs an empty cache. + * + * @param aMgr + * Bean manager. + */ + public InjectorCache(InjectorFactory aInjectorFactory) { + injectorFactory = aInjectorFactory; + injectors = new ConcurrentHashMap(); + } + + /** + * Gets the injector for a given class. This returns a cached injector or + * creates a new injector and caches it. + * + * @param aClass + * Class to find injector for. + * @return Injector. + */ + public Injector getInjector(Class aClass) { + Injector injector = injectors.get(aClass.getName()); + if (injector == null) { + // create and add injector + // NOTE: in rare circumstances this will lead to parallel + // creation of + // an injector for the same class. However, only one of them + // will be the final one + // in the map. There are no side effects of this duplicate + // creation of injectors. + injector = injectorFactory.create(aClass); + injectors.put(aClass.getName(), injector); + } + return injector; + } +} diff --git a/support/cdi/src/main/java/org/wamblee/cdi/InjectorFactory.java b/support/cdi/src/main/java/org/wamblee/cdi/InjectorFactory.java new file mode 100644 index 00000000..1761d24a --- /dev/null +++ b/support/cdi/src/main/java/org/wamblee/cdi/InjectorFactory.java @@ -0,0 +1,27 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.cdi; + +/** + * Injector factory used. This may be subclasses for testing. + * + * @author Erik Brakkee + */ +public interface InjectorFactory { + + Injector create(Class aClass); + +} diff --git a/support/cdi/src/main/java/org/wamblee/cdi/SimpleInjector.java b/support/cdi/src/main/java/org/wamblee/cdi/SimpleInjector.java new file mode 100644 index 00000000..7a8db0da --- /dev/null +++ b/support/cdi/src/main/java/org/wamblee/cdi/SimpleInjector.java @@ -0,0 +1,48 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.cdi; + +/** + * Singleton injector access. This should be used as main entry point for + * injection. A different {@link InjectorFactory} can be plugged in for testing. + * + * @author Erik Brakkee + */ +public class SimpleInjector { + + private static InjectorCache cache = new InjectorCache( + new CdiInjectorFactory()); + + /** + * Override the injector factory (mainly fo runit test). + * + * @param aFactory + * Factory. + */ + public static void setInjectorFactory(InjectorFactory aFactory) { + cache = new InjectorCache(aFactory); + } + + /** + * Injects into a given object. + * + * @param aObject + * Object to inject into. + */ + public static void inject(Object aObject) { + cache.getInjector(aObject.getClass()).inject(aObject); + } +} diff --git a/support/cdi/src/test/java/org/wamblee/cdi/MyPojo.java b/support/cdi/src/test/java/org/wamblee/cdi/MyPojo.java new file mode 100644 index 00000000..b207c639 --- /dev/null +++ b/support/cdi/src/test/java/org/wamblee/cdi/MyPojo.java @@ -0,0 +1,17 @@ +package org.wamblee.cdi; + +import javax.inject.Inject; + +public class MyPojo { + + @Inject + private MySingleton singleton; + + public MyPojo() { + // Empty. + } + + public MySingleton getSingleton() { + return singleton; + } +} diff --git a/support/cdi/src/test/java/org/wamblee/cdi/MySingleton.java b/support/cdi/src/test/java/org/wamblee/cdi/MySingleton.java new file mode 100644 index 00000000..7754c547 --- /dev/null +++ b/support/cdi/src/test/java/org/wamblee/cdi/MySingleton.java @@ -0,0 +1,19 @@ +package org.wamblee.cdi; + +import javax.enterprise.context.ApplicationScoped; + + +@ApplicationScoped +public class MySingleton { + + private static int instances = 0; + + public MySingleton() { + System.out.println("Constructing object."); + instances++; + } + + public static int getInstances() { + return instances; + } +} diff --git a/support/cdi/src/test/java/org/wamblee/cdi/WeldTest.java b/support/cdi/src/test/java/org/wamblee/cdi/WeldTest.java new file mode 100644 index 00000000..c8608825 --- /dev/null +++ b/support/cdi/src/test/java/org/wamblee/cdi/WeldTest.java @@ -0,0 +1,55 @@ +package org.wamblee.cdi; + +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.AnnotatedType; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.InjectionTarget; + +import org.jboss.weld.environment.se.Weld; +import org.jboss.weld.environment.se.WeldContainer; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import static junit.framework.TestCase.*; + +public class WeldTest { + + private Weld weld; + private WeldContainer container; + private BeanManager beanManager; + + @Before + public void setUp() { + weld = new Weld(); + container = weld.initialize(); + beanManager = container.getBeanManager(); + } + + @After + public void tearDown() { + weld.shutdown(); + } + + @Test + public void testGetSingleton() { + AnnotatedType type = beanManager.createAnnotatedType(MyPojo.class); + InjectionTarget target = beanManager.createInjectionTarget(type); + CreationalContext ctx = beanManager.createCreationalContext(null); + + MyPojo pojo = new MyPojo(); + + target.inject(pojo, ctx); + + MySingleton obj = pojo.getSingleton(); + + assertNotNull(obj); + + MyPojo pojo2 = new MyPojo(); + target.inject(pojo2, ctx); + + // Objects will not be the same as they are contextual references to the same object. + // assertSame(pojo2, pojo); + + assertEquals(1, MySingleton.getInstances()); + } +} diff --git a/support/cdi/src/test/resources/META-INF/beans.xml b/support/cdi/src/test/resources/META-INF/beans.xml new file mode 100644 index 00000000..82ec09d9 --- /dev/null +++ b/support/cdi/src/test/resources/META-INF/beans.xml @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/support/general/pom.xml b/support/general/pom.xml index b0017cd5..8354f98f 100644 --- a/support/general/pom.xml +++ b/support/general/pom.xml @@ -61,7 +61,7 @@ - test-enterprise-site + support-general file:${distrib}/support/general diff --git a/support/pom.xml b/support/pom.xml index 31be4b22..c31a7276 100644 --- a/support/pom.xml +++ b/support/pom.xml @@ -16,6 +16,7 @@ general + cdi spring -- 2.31.1