package org.jboss.seam.test.integration; import java.io.Serializable; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.persistence.EntityManager; import org.jboss.seam.Component; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.AutoCreate; import org.jboss.seam.annotations.Begin; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.contexts.Contexts; import org.jboss.seam.core.Conversation; import org.jboss.seam.mock.SeamTest; import org.jboss.seam.persistence.ManagedEntityInterceptor; import org.testng.annotations.Test; /** * Verifies the work of the ManagedEntityInterceptor. Specifically that * collections containing entity instances are properly put into the session and * pulled back into the conversation-scoped component between requests (during a * potential period of passivation of the SFSB). The test also verifies that * when a component in a nested conversation calls a component in a parent * conversation, that the passivated state is kept with the parent conversation. * * @author Norman Richards * @author Dan Allen */ public class EntityPassivationTest extends SeamTest { @Test public void testEntityList() throws Exception { String pid = new FacesRequest("/test.xhtml") { @Override protected void invokeApplication() throws Exception { // MEI is not installed by default, so we need to enable it Component.forName("entitytest.someComponent").addInterceptor(new ManagedEntityInterceptor()); Component.forName("entitytest.nestedComponent").addInterceptor(new ManagedEntityInterceptor()); Conversation.instance().begin(true, false); invokeAction("#{entitytest.someComponent.createSomeThings}"); invokeAction("#{entitytest.someComponent.loadThings}"); } @Override protected void renderResponse() throws Exception { Object thing = getValue("#{entitytest.someComponent.thing}"); assert thing != null; List thingList = (List) getValue("#{entitytest.someComponent.thingsAsList}"); assert thingList != null && !thingList.isEmpty(); assert thingList.get(0) != null; Set thingSet = (Set) getValue("#{entitytest.someComponent.thingsAsSet}"); assert thingSet != null && thingSet.size() > 0; assert thingSet.iterator().next() != null; Map thingMap = (Map) getValue("#{entitytest.someComponent.thingsAsMap}"); assert thingMap != null && thingMap.size() > 0; } }.run(); new FacesRequest("/test.xhtml", pid) { // the entities should be passivated }.run(); new FacesRequest("/test.xhtml", pid) { // passivated a second time }.run(); new FacesRequest("/test.xhtml", pid) { @Override protected void renderResponse() throws Exception { Object thing = getValue("#{entitytest.someComponent.thing}"); assert thing != null; List thingList = (List) getValue("#{entitytest.someComponent.thingsAsList}"); assert thingList != null && !thingList.isEmpty(); assert thingList.get(0) != null; Set thingSet = (Set) getValue("#{entitytest.someComponent.thingsAsSet}"); assert thingSet != null && thingSet.size() > 0; assert thingSet.iterator().next() != null; Map thingMap = (Map) getValue("#{entitytest.someComponent.thingsAsMap}"); assert thingMap != null && thingMap.size() > 0; } }.run(); // Start a nested conversation to verify that calls to a component in a parent conversation // will passivate that component's state in the parent conversation context and not in // the nested conversation. Thus, when the parent conversation is restored, its state // will be properly restored. String nid = new FacesRequest("/test.xhtml", pid) { @Override protected void invokeApplication() throws Exception { invokeMethod("#{entitytest.nestedComponent.nest}"); } @Override protected void renderResponse() throws Exception { assert Conversation.instance().isNested(); } }.run(); new FacesRequest("/test.xhtml", nid) { @Override protected void invokeApplication() throws Exception { // invoke component in parent conversation from nested conversation invokeMethod("#{entitytest.someComponent.removeFirstThingFromList}"); } @Override protected void renderResponse() throws Exception { // the nested conversation should not hold the serialized property of the component in the parent conversation assert !Arrays.asList(Contexts.getConversationContext().getNames()).contains("entitytest.someComponent.thingList"); List thingList = (List) getValue("#{entitytest.someComponent.thingsAsList}"); assert thingList.size() == 1; } }.run(); new FacesRequest("/test.xhtml", nid) { @Override protected void invokeApplication() throws Exception { invokeMethod("#{entitytest.nestedComponent.end}"); } }.run(); new FacesRequest("/test.xhtml", pid) { @Override protected void renderResponse() throws Exception { // The state of the component in the parent conversation should be preserved. List thingList = (List) getValue("#{entitytest.someComponent.thingsAsList}"); assert thingList.size() == 1; } }.run(); } @Name("entitytest.someComponent") @Scope(ScopeType.CONVERSATION) @AutoCreate public static class SomeComponent implements Serializable { @In EntityManager entityManager; Set<UnversionedThing> thingSet; List<UnversionedThing> thingList; Map<Long, UnversionedThing> thingMap; UnversionedThing thing; public void loadThings() { thingList = entityManager.createQuery("select t from UnversionedThing t").getResultList(); thingSet = new HashSet<UnversionedThing>(thingList); thingMap = new HashMap<Long, UnversionedThing>(); for (UnversionedThing thing : thingList) { thingMap.put(thing.getId(), thing); } thing = thingList.get(0); } public List<UnversionedThing> getThingsAsList() { return thingList; } public Set<UnversionedThing> getThingsAsSet() { return thingSet; } public Map<Long, UnversionedThing> getThingsAsMap() { return thingMap; } public UnversionedThing getThing() { return thing; } public void removeFirstThingFromList() { loadThings(); thingList.remove(0); } public void createSomeThings() { UnversionedThing thing1 = new UnversionedThing(); thing1.setName("thing one"); entityManager.persist(thing1); UnversionedThing thing2 = new UnversionedThing(); thing2.setName("thing two"); entityManager.persist(thing2); } } @Name("entitytest.nestedComponent") @Scope(ScopeType.CONVERSATION) @AutoCreate public static class NestedComponent implements Serializable { @In EntityManager entityManager; @Begin(nested = true) public void nest() { } public void end() { Conversation.instance().end(); } } }