From 8bfdb340898198e2dbc68374b357de4b66512389 Mon Sep 17 00:00:00 2001 From: Sean Flanigan Date: Fri, 26 Jun 2015 16:47:40 +1000 Subject: [PATCH] Import CDI version of ServiceLocator --- .../java/org/zanata/util/ServiceLocator.java | 72 +++++++---- .../org/zanata/util/ServiceLocatorTest.java | 116 ++++++++++++++++++ 2 files changed, 165 insertions(+), 23 deletions(-) create mode 100644 zanata-war/src/test/java/org/zanata/util/ServiceLocatorTest.java diff --git a/zanata-war/src/main/java/org/zanata/util/ServiceLocator.java b/zanata-war/src/main/java/org/zanata/util/ServiceLocator.java index 7845392293..81c0bfda1f 100644 --- a/zanata-war/src/main/java/org/zanata/util/ServiceLocator.java +++ b/zanata-war/src/main/java/org/zanata/util/ServiceLocator.java @@ -18,62 +18,88 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ - package org.zanata.util; +import org.apache.deltaspike.core.api.provider.BeanProvider; +import org.apache.deltaspike.core.api.provider.DependentProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import javax.naming.Context; import javax.naming.InitialContext; -import javax.naming.NameNotFoundException; import javax.naming.NamingException; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; - -import org.jboss.seam.Component; -import org.jboss.seam.ScopeType; -import org.jboss.seam.annotations.AutoCreate; -import org.jboss.seam.annotations.Name; -import org.jboss.seam.annotations.Scope; -import org.jboss.seam.annotations.intercept.BypassInterceptors; +import java.lang.annotation.Annotation; /** - * Service Locator for Seam components, intended for obtaining short-lived + * Service Locator for CDI beans, intended for obtaining short-lived * components to use inside methods of long-lived components, such as DAOs * inside application scope singletons. *

+ * NOTE: BeanProvider will log a warning (via JUL) if getInstance returns a + * dependent bean (you should use getDependent instead to for correct + * lifecycle handling). + *

* It's still an anti-pattern, but at least this way callers don't use * Component.getInstance() directly, and ServiceLocator can be subclassed * to return mock objects for testing. * @author Sean Flanigan sflaniga@redhat.com - * + * @author Carlos Munoz camunoz@redhat.com */ -@AutoCreate -@BypassInterceptors -@Name("serviceLocator") -@Scope(ScopeType.STATELESS) public class ServiceLocator { + private static Logger log = LoggerFactory.getLogger(ServiceLocator.class); + + private static final ServiceLocator INSTANCE = new ServiceLocator(); public static ServiceLocator instance() { - return (ServiceLocator) Component.getInstance(ServiceLocator.class); + return INSTANCE; } - public T getInstance(Class clazz) { - return (T) Component.getInstance(clazz); + private ServiceLocator() { } + /** + * @deprecated Use class and/or qualifiers, not name + */ + @Deprecated + public DependentProvider getDependent(String name, Class clazz) { + log.warn("Still using name in getDependent({}, {})", name, clazz); + return BeanProvider.getDependent(name); + } + + public DependentProvider getDependent(Class clazz, Annotation... qualifiers) { + return BeanProvider.getDependent(clazz, qualifiers); + } + + /** + * @deprecated Use class and/or qualifiers, not name + */ + @Deprecated public T getInstance(String name, Class clazz) { - return (T) Component.getInstance(name); + log.warn("Still using name in getInstance({}, {})", name, clazz); + return BeanProvider.getContextualReference(name, false, clazz); + } + + public T getInstance(Class clazz, Annotation... qualifiers) { + return BeanProvider.getContextualReference(clazz, qualifiers); } - public T getInstance(String name, ScopeType scope, Class clazz) { - return (T) Component.getInstance(name, scope); + /** + * @deprecated Use class and/or qualifiers, not name + */ + @Deprecated + public T getInstance(String name, Object scope, Class clazz) { + log.warn("Ignoring scope in getInstance({}, {}, {})", name, scope, clazz); + return (T) getInstance(name, clazz); } public EntityManager getEntityManager() { - return (EntityManager) Component.getInstance("entityManager"); + return getInstance(EntityManager.class); } public EntityManagerFactory getEntityManagerFactory() { - return (EntityManagerFactory) Component.getInstance("entityManagerFactory"); + return getInstance(EntityManagerFactory.class); } public T getJndiComponent(String jndiName, Class clazz) diff --git a/zanata-war/src/test/java/org/zanata/util/ServiceLocatorTest.java b/zanata-war/src/test/java/org/zanata/util/ServiceLocatorTest.java new file mode 100644 index 0000000000..e76a111d8f --- /dev/null +++ b/zanata-war/src/test/java/org/zanata/util/ServiceLocatorTest.java @@ -0,0 +1,116 @@ +/* + * Copyright 2014, Red Hat, Inc. and individual contributors as indicated by the + * @author tags. See the copyright.txt file in the distribution for a full + * listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this software; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF + * site: http://www.fsf.org. + */ +package org.zanata.util; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.logging.LogManager; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.inject.Named; + +import org.apache.deltaspike.core.api.projectstage.ProjectStage; +import org.apache.deltaspike.core.api.provider.BeanProvider; +import org.apache.deltaspike.core.util.ProjectStageProducer; +import org.jglue.cdiunit.AdditionalClasspaths; +import org.jglue.cdiunit.CdiRunner; +import org.jglue.cdiunit.InRequestScope; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.bridge.SLF4JBridgeHandler; + +@AdditionalClasspaths(BeanProvider.class) +@InRequestScope +@RunWith(CdiRunner.class) +public class ServiceLocatorTest { + + static { + // redirect JUL to slf4j + LogManager.getLogManager().reset(); + SLF4JBridgeHandler.install(); + + // Tell DeltaSpike to give more warning messages + ProjectStageProducer.getInstance().setProjectStage(ProjectStage.UnitTest); + } + + @Named + public static class DependentBean { + } + + @Named("myNamedBean") + @RequestScoped + public static class ExplicitlyNamedBean { + } + + @Named + @RequestScoped + public static class NamedBean { + } + + @Inject + private DependentBean dependentBean; + + @Inject + private ExplicitlyNamedBean myNamedBean; + + @Inject + private NamedBean namedBean; + + @Inject + private ServiceLocator locator; + + @Test + public void dependentBeanByClass() throws Exception { + DependentBean got = locator.getInstance(DependentBean.class); + assertThat(got).isNotEqualTo(dependentBean); + assertThat(got.getClass()).isEqualTo(dependentBean.getClass()); + } + + @Test + public void dependentBeanByName() throws Exception { + DependentBean got = + locator.getInstance("dependentBean", DependentBean.class); + assertThat(got).isNotEqualTo(dependentBean); + assertThat(got.getClass()).isEqualTo(dependentBean.getClass()); + } + + @Test + public void explicitlyNamedBeanByClass() throws Exception { + assertThat(locator.getInstance(ExplicitlyNamedBean.class)).isEqualTo(myNamedBean); + } + + @Test + public void explicitlyNamedBeanByName() throws Exception { + assertThat(locator.getInstance("myNamedBean", ExplicitlyNamedBean.class)).isEqualTo(myNamedBean); + } + + @Test + public void namedBeanByClass() throws Exception { + assertThat(locator.getInstance(NamedBean.class)).isEqualTo(namedBean); + } + + @Test + public void namedBeanByName() throws Exception { + assertThat(locator.getInstance("namedBean", NamedBean.class)).isEqualTo(namedBean); + } + +}