/** * Copyright (C) 2016 Red Hat, Inc. and/or its affiliates. * * 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.jboss.errai.ioc.tests.beanmanager.client; import static org.jboss.errai.ioc.client.QualifierUtil.DEFAULT_ANNOTATION; import static org.jboss.errai.ioc.client.container.IOC.getBeanManager; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.jboss.errai.ioc.client.api.ManagedInstance; import org.jboss.errai.ioc.client.container.Factory; import org.jboss.errai.ioc.client.container.IOC; import org.jboss.errai.ioc.client.test.AbstractErraiIOCTest; import org.jboss.errai.ioc.tests.beanmanager.client.res.A; import org.jboss.errai.ioc.tests.beanmanager.client.res.B; import org.jboss.errai.ioc.tests.beanmanager.client.res.BeanWithManagedInstance; import org.jboss.errai.ioc.tests.beanmanager.client.res.C; import org.jboss.errai.ioc.tests.beanmanager.client.res.DefaultDependentBean; import org.jboss.errai.ioc.tests.beanmanager.client.res.DestructableClass; import org.jboss.errai.ioc.tests.beanmanager.client.res.OtherDestructableClass; /** * * @author Max Barkley <mbarkley@redhat.com> */ public class ManagedInstanceTest extends AbstractErraiIOCTest { private static final A a = new A() { @Override public Class<? extends Annotation> annotationType() { return A.class; } }; private static final B b = new B() { @Override public Class<? extends Annotation> annotationType() { return B.class; } }; private static final C c = new C() { @Override public Class<? extends Annotation> annotationType() { return C.class; } }; private BeanWithManagedInstance module; @Override public String getModuleName() { return "org.jboss.errai.ioc.tests.beanmanager.IOCBeanManagerTests"; } @Override protected void gwtSetUp() throws Exception { super.gwtSetUp(); module = IOC.getBeanManager().lookupBean(BeanWithManagedInstance.class).getInstance(); } public void testResolvesDefaultWithNoExplicitQualifiers() throws Exception { final List<DestructableClass> beans = fromIterator(module.defaultOnly.iterator()); assertTrue(module.defaultOnly.isAmbiguous()); assertEquals(2, beans.size()); for (final DestructableClass instance : beans) { assertTrue(getSimpleName(instance) + " is not @Default but was resolved.", instance.isDefault()); } } public void testResolvesAllWithAnyQualifier() throws Exception { final List<DestructableClass> beans = fromIterator(module.any.iterator()); assertTrue(module.any.isAmbiguous()); assertEquals(4, beans.size()); } public void testDoesNotResolveDefaultWithOtherQualifier() throws Exception { final List<DestructableClass> beans = fromIterator(module.aOnly.iterator()); assertTrue(module.aOnly.isAmbiguous()); assertEquals(2, beans.size()); for (final DestructableClass instance : beans) { assertFalse(getSimpleName(instance) + " is @Default but was resolved.", instance.isDefault()); } } public void testDoesNotResolveAnythingForUnsatisfiableCombination() throws Exception { final List<DestructableClass> beans = fromIterator(module.unsatisfied.iterator()); assertTrue(module.unsatisfied.isUnsatisfied()); assertEquals(0, beans.size()); } public void testDestroyAllDestroysCreatedDependentScopedBeans() throws Exception { final List<DestructableClass> beans = fromIterator(module.any.iterator()); final List<DestructableClass> depBeans = getDependent(beans); final List<DestructableClass> normalBeans = getNormalScoped(beans); // Preconditions assertEquals(2, depBeans.size()); assertEquals(2, normalBeans.size()); for (final DestructableClass instance : beans) { assertFalse(getSimpleName(instance) + " was destroyed before destroyAll was called.", instance.isDestroyed()); } // Test module.any.destroyAll(); for (final DestructableClass instance : depBeans) { assertTrue(getSimpleName(instance) + " was not destroyed after destroyAll was called.", instance.isDestroyed()); } for (final DestructableClass instance : normalBeans) { assertFalse(getSimpleName(instance) + " was destroyed after destroyAll was called.", instance.isDestroyed()); } } public void testSelectingQualifierResolution() throws Exception { final ManagedInstance<DestructableClass> selectedInstance = module.any.select(a); final List<DestructableClass> beans = fromIterator(selectedInstance.iterator()); assertTrue(selectedInstance.isAmbiguous()); assertEquals(2, beans.size()); for (final DestructableClass instance : beans) { assertFalse(getSimpleName(instance) + " is @Default but was resolved.", instance.isDefault()); } } public void testSelectingSubtypeResolution() throws Exception { final ManagedInstance<DefaultDependentBean> selectedInstance = module.any.select(DefaultDependentBean.class); final List<DefaultDependentBean> beans = fromIterator(selectedInstance.iterator()); assertFalse(selectedInstance.isAmbiguous()); assertFalse(selectedInstance.isUnsatisfied()); assertEquals(1, beans.size()); assertTrue(beans.iterator().next().isDependent()); assertTrue(beans.iterator().next().isDefault()); } public void testDestroyAllOnSelectedAnnotationDoesNotAffectInjectedOrOtherSelectedInstances() throws Exception { final ManagedInstance<DestructableClass> aInstance = module.any.select(a); final ManagedInstance<DestructableClass> defaultInstance = module.any.select(DEFAULT_ANNOTATION); final List<DestructableClass> aBeans = fromIterator(aInstance.iterator()); final List<DestructableClass> defaultBeans = fromIterator(defaultInstance.iterator()); final List<DestructableClass> anyBeans = fromIterator(module.any.iterator()); for (final DestructableClass instance : aBeans) { assertFalse(getSimpleName(instance) + " was destroyed before destroyAll was called.", instance.isDestroyed()); } for (final DestructableClass instance : defaultBeans) { assertFalse(getSimpleName(instance) + " was destroyed before destroyAll was called.", instance.isDestroyed()); } for (final DestructableClass instance : anyBeans) { assertFalse(getSimpleName(instance) + " was destroyed before destroyAll was called.", instance.isDestroyed()); } defaultInstance.destroyAll(); final List<DestructableClass> defaultDepBeans = getDependent(defaultBeans); final List<DestructableClass> defaultNormalBeans = getNormalScoped(defaultBeans); for (final DestructableClass instance : aBeans) { assertFalse(getSimpleName(instance) + " was destroyed after destroyAll was called.", instance.isDestroyed()); } for (final DestructableClass instance : anyBeans) { assertFalse(getSimpleName(instance) + " was destroyed after destroyAll was called.", instance.isDestroyed()); } for (final DestructableClass instance : defaultNormalBeans) { assertFalse(getSimpleName(instance) + " was destroyed after destroyAll was called.", instance.isDestroyed()); } for (final DestructableClass instance : defaultDepBeans) { assertTrue(getSimpleName(instance) + " was not destroyed after destroyAll was called.", instance.isDestroyed()); } } public void testDestroyAllOnSelectedSubtypeDoesNotAffectInjectedOrOtherSelectedInstances() throws Exception { final ManagedInstance<DefaultDependentBean> defaultDepBeanInstance = module.any.select(DefaultDependentBean.class); assertFalse("ManagedInstance<DefaultDependentBean> should not be ambiguous.", defaultDepBeanInstance.isAmbiguous()); assertFalse("ManagedInstance<DefaultDependentBean> should not be unsatisfied.", defaultDepBeanInstance.isUnsatisfied()); final DefaultDependentBean subtypeInstance = defaultDepBeanInstance.get(); assertFalse(getSimpleName(subtypeInstance) + " was destroyed before destroyAll was called.", subtypeInstance.isDestroyed()); final List<DestructableClass> anyBeans = fromIterator(module.any.iterator()); assertEquals(4, anyBeans.size()); for (final DestructableClass instance : anyBeans) { assertFalse(getSimpleName(instance) + " was destroyed before destroyAll was called.", instance.isDestroyed()); } defaultDepBeanInstance.destroyAll(); assertTrue(getSimpleName(subtypeInstance) + " was not destroyed after destroyAll was called.", subtypeInstance.isDestroyed()); for (final DestructableClass instance : anyBeans) { assertFalse(getSimpleName(instance) + " was destroyed after destroyAll was called on subtype instance.", instance.isDestroyed()); } } public void testDestroyingBeanWithInjectedManagedInstanceDestroysAllCreatedInstances() throws Exception { // Setup final List<DestructableClass> anyBeans = fromIterator(module.any.iterator()); final ManagedInstance<DestructableClass> aInstance = module.any.select(a); final List<DestructableClass> aBeans = fromIterator(aInstance.iterator()); final List<DestructableClass> depBeans = getDependent(anyBeans); depBeans.addAll(getDependent(aBeans)); final List<DestructableClass> normalBeans = getNormalScoped(anyBeans); normalBeans.addAll(getNormalScoped(aBeans)); // Preconditions for (final DestructableClass instance : aBeans) { assertFalse(getSimpleName(instance) + " was destroyed before module was destroyed.", instance.isDestroyed()); } for (final DestructableClass instance : anyBeans) { assertFalse(getSimpleName(instance) + " was destroyed before module was destroyed.", instance.isDestroyed()); } // Test getBeanManager().destroyBean(module); assertTrue("The bean containing the injected managed instance was not destroyed.", module.isDestroyed()); for (final DestructableClass instance : normalBeans) { assertFalse(getSimpleName(instance) + " was destroyed after module was destroyed.", instance.isDestroyed()); } for (final DestructableClass instance : depBeans) { assertTrue(getSimpleName(instance) + " was not destroyed after module was destroyed.", instance.isDestroyed()); } } public void testDestroyingProducedBeanOfApplicationScopedProducerUsingParamInjectedManagedInstance() throws Exception { final OtherDestructableClass producedBean = getBeanManager().lookupBean(OtherDestructableClass.class, a).getInstance(); assertFalse(producedBean.isDestroyed()); getBeanManager().destroyBean(producedBean); assertTrue(producedBean.isDestroyed()); } public void testDestroyingProducedBeanOfDepdendentScopedProducerUsingParamInjectedManagedInstance() throws Exception { final OtherDestructableClass producedBean = getBeanManager().lookupBean(OtherDestructableClass.class, b).getInstance(); assertFalse(producedBean.isDestroyed()); getBeanManager().destroyBean(producedBean); assertTrue(producedBean.isDestroyed()); } public void testDestroyingProducedBeanOfDependentScopedProducerUsingFieldInjectedManagedInstance() throws Exception { final OtherDestructableClass producedBean = getBeanManager().lookupBean(OtherDestructableClass.class, c).getInstance(); assertFalse(producedBean.isDestroyed()); getBeanManager().destroyBean(producedBean); assertTrue(producedBean.isDestroyed()); } private static String getSimpleName(final DestructableClass instance) { return Factory.maybeUnwrapProxy(instance).getClass().getSimpleName(); } private static <T> List<T> fromIterator(final Iterator<T> iter) { final List<T> list = new ArrayList<>(); while (iter.hasNext()) { list.add(iter.next()); } return list; } private static List<DestructableClass> getDependent(final List<DestructableClass> all) { final List<DestructableClass> list = new ArrayList<>(); for (final DestructableClass instance : all) { if (instance.isDependent()) { list.add(instance); } } return list; } private static List<DestructableClass> getNormalScoped(final List<DestructableClass> all) { final List<DestructableClass> list = new ArrayList<>(); for (final DestructableClass instance : all) { if (!instance.isDependent()) { list.add(instance); } } return list; } }