/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.cdi.tck.tests.implementation.simple.lifecycle;
import static org.jboss.cdi.tck.cdi.Sections.BEAN_ARCHIVE_EE;
import static org.jboss.cdi.tck.cdi.Sections.CONCEPTS;
import static org.jboss.cdi.tck.cdi.Sections.CONTEXT;
import static org.jboss.cdi.tck.cdi.Sections.CONTEXTUAL;
import static org.jboss.cdi.tck.cdi.Sections.CONTEXTUAL_REFERENCE;
import static org.jboss.cdi.tck.cdi.Sections.CREATIONAL_CONTEXT;
import static org.jboss.cdi.tck.cdi.Sections.DECLARING_BEAN_CONSTRUCTOR;
import static org.jboss.cdi.tck.cdi.Sections.DECLARING_INJECTED_FIELD;
import static org.jboss.cdi.tck.cdi.Sections.DEPENDENT_OBJECTS_DESTRUCTION;
import static org.jboss.cdi.tck.cdi.Sections.INITIALIZATION;
import static org.jboss.cdi.tck.cdi.Sections.INJECTED_FIELDS;
import static org.jboss.cdi.tck.cdi.Sections.INJECTED_FIELD_QUALIFIERS;
import static org.jboss.cdi.tck.cdi.Sections.LEGAL_BEAN_TYPES;
import static org.jboss.cdi.tck.cdi.Sections.MANAGED_BEAN_LIFECYCLE;
import static org.jboss.cdi.tck.cdi.Sections.MEMBER_LEVEL_INHERITANCE;
import static org.jboss.cdi.tck.cdi.Sections.METHOD_CONSTRUCTOR_PARAMETER_QUALIFIERS;
import static org.jboss.cdi.tck.cdi.Sections.PASSIVATION_CAPABLE_DEPENDENCY;
import static org.jboss.cdi.tck.cdi.Sections.SPECIALIZE_MANAGED_BEAN;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.lang.annotation.Annotation;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.spi.Context;
import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.CreationException;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.Specializes;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.util.AnnotationLiteral;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.cdi.tck.AbstractTest;
import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder;
import org.jboss.cdi.tck.util.DependentInstance;
import org.jboss.cdi.tck.util.MockCreationalContext;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.test.audit.annotations.SpecAssertion;
import org.jboss.test.audit.annotations.SpecAssertions;
import org.jboss.test.audit.annotations.SpecVersion;
import org.testng.annotations.Test;
@SpecVersion(spec = "cdi", version = "2.0-PFD")
public class SimpleBeanLifecycleTest extends AbstractTest {
private static final Annotation TAME_LITERAL = new AnnotationLiteral<Tame>() {
};
@Deployment
public static WebArchive createTestArchive() {
return new WebArchiveBuilder().withTestClassPackage(SimpleBeanLifecycleTest.class).withBeansXml("beans.xml").build();
}
@Test
@SpecAssertions({ @SpecAssertion(section = DECLARING_BEAN_CONSTRUCTOR, id = "f"), @SpecAssertion(section = DECLARING_BEAN_CONSTRUCTOR, id = "g"),
@SpecAssertion(section = METHOD_CONSTRUCTOR_PARAMETER_QUALIFIERS, id = "d") })
public void testInjectionOfParametersIntoBeanConstructor() {
assert getBeans(FishPond.class).size() == 1;
FishPond fishPond = getContextualReference(FishPond.class);
assert fishPond.goldfish != null;
assert fishPond.goldfish instanceof Goldfish;
assert fishPond.goose != null;
}
@Test
@SpecAssertions({ @SpecAssertion(section = PASSIVATION_CAPABLE_DEPENDENCY, id = "b") })
public void testSerializeRequestScoped() throws Exception {
Cod codInstance = getContextualReference(Cod.class);
byte[] bytes = passivate(codInstance);
Object object = activate(bytes);
codInstance = (Cod) object;
assert getCurrentConfiguration().getBeans().isProxy(codInstance);
}
@Test
@SpecAssertions({ @SpecAssertion(section = PASSIVATION_CAPABLE_DEPENDENCY, id = "b") })
public void testSerializeSessionScoped() throws Exception {
Bream instance = getContextualReference(Bream.class);
byte[] bytes = passivate(instance);
Object object = activate(bytes);
instance = (Bream) object;
assert getCurrentConfiguration().getBeans().isProxy(instance);
}
@Test
@SpecAssertion(section = DECLARING_BEAN_CONSTRUCTOR, id = "g")
public void testQualifierTypeAnnotatedConstructor() {
getContextualReference(Duck.class);
assert Duck.constructedCorrectly;
}
@Test
@SpecAssertions({ @SpecAssertion(section = SPECIALIZE_MANAGED_BEAN, id = "ac") })
public void testSpecializedBeanExtendsManagedBean() {
assert MountainLion.class.getAnnotation(Specializes.class) != null;
Bean<Lion> bean = null;
Bean<Lion> specializedBean = null;
for (Bean<Lion> lionBean : getBeans(Lion.class, TAME_LITERAL)) {
if (lionBean.getBeanClass().equals(Lion.class)) {
bean = lionBean;
} else if (lionBean.getBeanClass().equals(MountainLion.class)) {
specializedBean = lionBean;
}
}
assert bean == null;
assert specializedBean != null;
assert specializedBean.getBeanClass().getSuperclass().equals(Lion.class);
}
@Test
@SpecAssertions({ @SpecAssertion(section = CREATIONAL_CONTEXT, id = "d"), @SpecAssertion(section = CREATIONAL_CONTEXT, id = "g") })
public void testCreateReturnsSameBeanPushed() {
final CreationalContext<ShoeFactory> creationalContext = new MockCreationalContext<ShoeFactory>();
final Contextual<ShoeFactory> bean = getBeans(ShoeFactory.class).iterator().next();
MockCreationalContext.reset();
ShoeFactory instance = getCurrentManager().getContext(Dependent.class).get(bean, creationalContext);
if (MockCreationalContext.isPushCalled()) {
assert instance == MockCreationalContext.getLastBeanPushed();
}
}
@Test
@SpecAssertions({ @SpecAssertion(section = MANAGED_BEAN_LIFECYCLE, id = "aa") })
public void testBeanCreateInjectsDependenciesAndInvokesInitializerToInstantiateInstance() {
MockCreationalContext.reset();
final CreationalContext<FishPond> creationalContext = new MockCreationalContext<FishPond>();
final Contextual<FishPond> bean = getBeans(FishPond.class).iterator().next();
FishPond fishPond = bean.create(creationalContext);
assert fishPond != null;
assert fishPond.goldfish != null;
assert fishPond.goldfish instanceof Goldfish;
assert fishPond.goose != null;
assert fishPond.salmon != null;
assert fishPond.postConstructCalled; // required by Managed Bean specification
}
@Test
@SpecAssertions({ @SpecAssertion(section = CONCEPTS, id = "g"), @SpecAssertion(section = LEGAL_BEAN_TYPES, id = "b"),
@SpecAssertion(section = LEGAL_BEAN_TYPES, id = "k"), @SpecAssertion(section = INITIALIZATION, id = "ja") })
public void testManagedBean() {
assert getBeans(RedSnapper.class).size() == 1;
assert getContextualReference(RedSnapper.class) instanceof RedSnapper;
RedSnapper redSnapper = getContextualReference(RedSnapper.class);
redSnapper.ping();
assert redSnapper.isTouched();
}
@Test
@SpecAssertions({ @SpecAssertion(section = MANAGED_BEAN_LIFECYCLE, id = "aa"), @SpecAssertion(section = DECLARING_BEAN_CONSTRUCTOR, id = "aa"),
@SpecAssertion(section = INJECTED_FIELD_QUALIFIERS, id = "a"), @SpecAssertion(section = INJECTED_FIELDS, id = "a"),
@SpecAssertion(section = DECLARING_INJECTED_FIELD, id = "aa"), @SpecAssertion(section = BEAN_ARCHIVE_EE, id = "jg") })
public void testCreateInjectsFieldsDeclaredInJava() {
assert getBeans(TunaFarm.class).size() == 1;
TunaFarm tunaFarm = getContextualReference(TunaFarm.class);
assert tunaFarm.tuna != null;
assert tunaFarm.tuna.getName().equals("Ophir");
assert tunaFarm.qualifiedTuna != null;
assert tunaFarm.qualifiedTuna.getName().equals("qualifiedTuna");
}
@Test
@SpecAssertions({ @SpecAssertion(section = CONTEXT, id = "l") })
public void testContextCreatesNewInstanceForInjection() {
Context requestContext = getCurrentManager().getContext(RequestScoped.class);
Bean<Tuna> tunaBean = getBeans(Tuna.class).iterator().next();
assert requestContext.get(tunaBean) == null;
TunaFarm tunaFarm = getContextualReference(TunaFarm.class);
assert tunaFarm.tuna != null;
}
@Test
@SpecAssertions({ @SpecAssertion(section = MANAGED_BEAN_LIFECYCLE, id = "aa"), @SpecAssertion(section = MANAGED_BEAN_LIFECYCLE, id = "ba") })
public void testPostConstructPreDestroy() {
assert getBeans(Farm.class).size() == 1;
Bean<Farm> farmBean = getBeans(Farm.class).iterator().next();
CreationalContext<Farm> creationalContext = getCurrentManager().createCreationalContext(farmBean);
Farm farm = farmBean.create(creationalContext);
assert farm.founded != null;
assert farm.initialStaff == 20;
assert farm.closed == null;
farmBean.destroy(farm, creationalContext);
assert farm.closed != null;
assert farm.farmOffice.noOfStaff == 0;
}
@Test
@SpecAssertions({ @SpecAssertion(section = CONTEXTUAL_REFERENCE, id = "aa"), @SpecAssertion(section = MANAGED_BEAN_LIFECYCLE, id = "ba"),
@SpecAssertion(section = CONTEXTUAL_REFERENCE, id = "c") })
public void testContextualDestroyDisposesWhenNecessary() {
final Bean<Goose> gooseBean = getBeans(Goose.class).iterator().next();
final CreationalContext<Goose> gooseCc = getCurrentManager().createCreationalContext(gooseBean);
final Goose goose = gooseBean.create(gooseCc);
// If the bean has a pseudo-scope, the container must obtain a contextual instance
assert !getCurrentConfiguration().getBeans().isProxy(goose);
assert !EggProducer.isEggDisposed();
assert !Egg.isEggDestroyed();
gooseBean.destroy(goose, gooseCc);
assert EggProducer.isEggDisposed();
assert !Egg.isEggDestroyed();
}
@Test
@SpecAssertions({ @SpecAssertion(section = CONTEXTUAL, id = "ab") })
public void testContextualDestroyCatchesException() {
Bean<Cod> codBean = getBeans(Cod.class).iterator().next();
CreationalContext<Cod> creationalContext = getCurrentManager().createCreationalContext(codBean);
Cod codInstance = codBean.create(creationalContext);
codInstance.ping();
codBean.destroy(codInstance, creationalContext);
assertTrue(Cod.isExpcetionThrown());
}
@Test
@SpecAssertions({ @SpecAssertion(section = DEPENDENT_OBJECTS_DESTRUCTION, id = "a") })
public void testDependentsDestroyedAfterPreDestroy() {
Bean<FishPond> pondBean = getBeans(FishPond.class).iterator().next();
CreationalContext<FishPond> creationalContext = getCurrentManager().createCreationalContext(pondBean);
FishPond fishPond = pondBean.create(creationalContext);
pondBean.destroy(fishPond, creationalContext);
assert Salmon.isBeanDestroyed();
}
@Test(dataProvider = ARQUILLIAN_DATA_PROVIDER)
@SpecAssertion(section = MEMBER_LEVEL_INHERITANCE, id = "baa")
public void testSubClassInheritsPostConstructOnSuperclass(Instance<Object> instance) {
OrderProcessor.postConstructCalled = false;
assertEquals(getBeans(CdOrderProcessor.class).size(), 1);
getContextualReference(CdOrderProcessor.class).order();
assertTrue(OrderProcessor.postConstructCalled);
assertNotNull(instance);
OrderProcessor.postConstructCalled = false;
instance.select(CdOrderProcessor.class).get().order();
assertTrue(OrderProcessor.postConstructCalled);
}
@Test
@SpecAssertion(section = MEMBER_LEVEL_INHERITANCE, id = "bac")
public void testIndirectSubClassInheritsPostConstructOnSuperclass() {
OrderProcessor.postConstructCalled = false;
assert getBeans(IndirectOrderProcessor.class).size() == 1;
getContextualReference(IndirectOrderProcessor.class).order();
assert OrderProcessor.postConstructCalled;
}
@Test
@SpecAssertion(section = MEMBER_LEVEL_INHERITANCE, id = "bba")
public void testSubClassInheritsPreDestroyOnSuperclass() {
OrderProcessor.preDestroyCalled = false;
assert getBeans(CdOrderProcessor.class).size() == 1;
DependentInstance<CdOrderProcessor> bean = newDependentInstance(CdOrderProcessor.class);
CdOrderProcessor instance = bean.get();
assertFalse(instance.equals(null));
bean.destroy();
assertTrue(OrderProcessor.preDestroyCalled);
}
@Test
@SpecAssertion(section = MEMBER_LEVEL_INHERITANCE, id = "bbc")
public void testIndirectSubClassInheritsPreDestroyOnSuperclass() {
OrderProcessor.preDestroyCalled = false;
assert getBeans(IndirectOrderProcessor.class).size() == 1;
DependentInstance<IndirectOrderProcessor> bean = newDependentInstance(IndirectOrderProcessor.class);
assertFalse(bean.get().equals(null));
bean.destroy();
assertTrue(OrderProcessor.preDestroyCalled);
}
@Test
@SpecAssertion(section = MEMBER_LEVEL_INHERITANCE, id = "baa")
public void testSubClassDoesNotInheritPostConstructOnSuperclassBlockedByIntermediateClass() {
assert getBeans(NovelOrderProcessor.class).size() == 1;
OrderProcessor.postConstructCalled = false;
getContextualReference(NovelOrderProcessor.class).order();
assert !OrderProcessor.postConstructCalled;
}
@Test
@SpecAssertion(section = MEMBER_LEVEL_INHERITANCE, id = "bba")
public void testSubClassDoesNotInheritPreDestroyConstructOnSuperclassBlockedByIntermediateClass() {
OrderProcessor.preDestroyCalled = false;
assert getBeans(NovelOrderProcessor.class).size() == 1;
DependentInstance<NovelOrderProcessor> bean = newDependentInstance(NovelOrderProcessor.class);
NovelOrderProcessor instance = bean.get();
assertFalse(instance.equals(null));
bean.destroy();
assertFalse(OrderProcessor.preDestroyCalled);
}
@Test(expectedExceptions = CreationException.class)
@SpecAssertion(section = CONTEXTUAL, id = "aa")
public void testCreationExceptionWrapsCheckedExceptionThrownFromCreate() {
assert getBeans(Lorry_Broken.class).size() == 1;
getContextualReference(Lorry_Broken.class);
}
@Test(expectedExceptions = FooException.class)
@SpecAssertion(section = CONTEXTUAL, id = "aa")
public void testUncheckedExceptionThrownFromCreateNotWrapped() {
assert getBeans(Van_Broken.class).size() == 1;
getContextualReference(Van_Broken.class);
}
}