/* * Copyright (C) 2009 eXo Platform SAS. * * 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.exoplatform.services.jcr.api.xa; import org.exoplatform.services.jcr.JcrAPIBaseTest; import org.exoplatform.services.jcr.datamodel.ItemData; import org.exoplatform.services.jcr.datamodel.ItemType; import org.exoplatform.services.jcr.datamodel.NodeData; import org.exoplatform.services.jcr.datamodel.QPathEntry; import org.exoplatform.services.jcr.impl.core.NodeImpl; import org.exoplatform.services.jcr.impl.core.SessionImpl; import org.exoplatform.services.transaction.TransactionService; import java.util.ArrayList; import java.util.List; import javax.jcr.Node; import javax.jcr.PathNotFoundException; import javax.jcr.Session; import javax.jcr.SimpleCredentials; import javax.naming.InitialContext; import javax.transaction.Transaction; import javax.transaction.UserTransaction; /** * Created by The eXo Platform SAS. <br> * * @author <a href="mailto:geaz@users.sourceforge.net">Gennady Azarenkov</a> * @version $Id: TestUserTransaction.java 11907 2008-03-13 15:36:21Z ksm $ */ public class TestUserTransaction extends JcrAPIBaseTest { private TransactionService txService; public void setUp() throws Exception { super.setUp(); txService = (TransactionService)container.getComponentInstanceOfType(TransactionService.class); } private List<Session> openSomeSessions() throws Exception { assertNotNull(txService); List<Session> someSessions = new ArrayList<Session>(); Session s1 = repository.login(new SimpleCredentials("admin", "admin".toCharArray()), session.getWorkspace().getName()); Node rootS1 = s1.getRootNode(); rootS1.addNode("someNode1"); rootS1.save(); someSessions.add(s1); Session s2 = repository.login(new SimpleCredentials("exo", "exo".toCharArray()), session.getWorkspace().getName()); Node rootS2 = s2.getRootNode(); rootS2.addNode("someNode2"); rootS2.save(); someSessions.add(s2); Session s3 = repository.login(new SimpleCredentials("exo", "exo".toCharArray()), session.getWorkspace().getName()); Node rootS3 = s3.getRootNode(); rootS3.addNode("someNode3"); rootS3.getNode("someNode2").remove(); rootS3.save(); someSessions.add(s3); Session s4 = repository.login(new SimpleCredentials("admin", "admin".toCharArray()), session.getWorkspace().getName()); Node rootS4 = s4.getRootNode(); Node n = rootS4.getNode("someNode3"); n.addNode("someNode4"); rootS4.getNode("someNode1").remove(); rootS4.save(); someSessions.add(s4); // some logouts session.logout(); someSessions.add(session); s1.logout(); // ...from setUp() session = (SessionImpl)repository.login(credentials, "ws"); someSessions.add(session); workspace = session.getWorkspace(); root = session.getRootNode(); valueFactory = session.getValueFactory(); return someSessions; } public void testCommit() throws Exception { assertNotNull(txService); List<Session> someSessions = openSomeSessions(); UserTransaction ut = txService.getUserTransaction(); ut.begin(); // we need to create the session within the transaction to ensure that it will be enlisted Session session = repository.login(credentials, "ws"); session.getRootNode().addNode("txcommit"); session.save(); assertNotNull(session.getItem("/txcommit")); Session s1 = repository.login(new SimpleCredentials("admin", "admin".toCharArray()), session.getWorkspace().getName()); try { assertNotNull(s1.getItem("/txcommit")); fail("PathNotFoundException should have be thrown"); } catch (PathNotFoundException e) { //ok } ut.commit(); assertNotNull(s1.getItem("/txcommit")); someSessions.clear(); } public void testRollback() throws Exception { assertNotNull(txService); UserTransaction ut = txService.getUserTransaction(); ut.begin(); // we need to create the session within the transaction to ensure that it will be enlisted Session session = repository.login(credentials, "ws"); session.getRootNode().addNode("txrollback"); session.save(); assertNotNull(session.getItem("/txrollback")); // Session s1 = repository.login(new SimpleCredentials("admin","admin".toCharArray()), // session.getWorkspace().getName()); ut.rollback(); try { assertNotNull(session.getItem("/txrollback")); fail("PathNotFoundException should have be thrown"); } catch (PathNotFoundException e) { } } public void testVersionable() throws Exception { //System workspace testVersionable("ws"); } public void testVersionable2() throws Exception { //Normal workspace testVersionable("ws1"); } private void testVersionable(String workspace) throws Exception { assertNotNull(txService); List<Session> someSessions = openSomeSessions(); UserTransaction ut = txService.getUserTransaction(); ut.begin(); // we need to create the session within the transaction to ensure that it will be enlisted Session session = repository.login(credentials, workspace); Node node = session.getRootNode().addNode("txcommit"); node.addMixin("mix:versionable"); session.save(); assertNotNull(session.getItem("/txcommit")); Session s1 = repository.login(new SimpleCredentials("admin", "admin".toCharArray()), session.getWorkspace().getName()); try { assertNotNull(s1.getItem("/txcommit")); fail("PathNotFoundException should have be thrown"); } catch (PathNotFoundException e) { } node.checkin(); ut.commit(); assertNotNull(s1.getItem("/txcommit")); Node txNode = (Node)s1.getItem("/txcommit"); txNode.checkout(); txNode.checkin(); txNode.checkout(); someSessions.clear(); } // we don't have JNID for JBossTS in standalone now public void _testUserTransactionFromJndi() throws Exception { assertNotNull(txService); InitialContext ctx = new InitialContext(); Object obj = ctx.lookup("UserTransaction"); UserTransaction ut = (UserTransaction)obj; ut.begin(); Session s1 = repository.login(new SimpleCredentials("admin", "admin".toCharArray()), session.getWorkspace().getName()); s1.getRootNode().addNode("txcommit1"); s1.save(); ut.commit(); assertNotNull(session.getItem("/txcommit1")); } public void testReuseUT() throws Exception { assertNotNull(txService); // TODO in JNDI only JOTM today //InitialContext ctx = new InitialContext(); //Object obj = ctx.lookup("UserTransaction"); //UserTransaction ut = (UserTransaction)obj; UserTransaction ut = txService.getUserTransaction(); ut.begin(); Session s1 = repository.login(new SimpleCredentials("admin", "admin".toCharArray()), session.getWorkspace().getName()); Node tx2 = s1.getRootNode().addNode("txcommit2"); ut.commit(); ut.begin(); tx2.addNode("txcommit21"); s1.save(); ut.commit(); assertNotNull(session.getItem("/txcommit2/txcommit21")); } public void testAddRemoveNode() throws Exception { UserTransaction ut = txService.getUserTransaction(); root.addNode("Node"); session.save(); ut.begin(); Node node = root.getNode("Node"); String uuid = ((NodeImpl)node).getIdentifier(); node.setProperty("name", "value"); session.save(); node.remove(); session.save(); ItemData itemData = session.getTransientNodesManager().getItemData(uuid); boolean hasItemData = session.getTransientNodesManager().hasItemData((NodeData)((NodeImpl)root).getData(), QPathEntry.parse("[]Node:1"), ItemType.NODE); ut.commit(); assertNull(itemData); assertFalse(hasItemData); } public void testSaveException() throws Exception { assertNotNull(txService); // TODO in JNDI only JOTM today //InitialContext ctx = new InitialContext(); //Object obj = ctx.lookup("UserTransaction"); //UserTransaction ut = (UserTransaction)obj; UserTransaction ut = txService.getUserTransaction(); Session s0 = repository.login(new SimpleCredentials("root", "exo".toCharArray()), session.getWorkspace().getName()); Node pretx = s0.getRootNode().addNode("pretx"); s0.save(); pretx.remove(); // don't save now ut.begin(); Session s1 = repository.login(new SimpleCredentials("admin", "admin".toCharArray()), session.getWorkspace().getName()); Session s2 = repository.login(new SimpleCredentials("admin", "admin".toCharArray()), session.getWorkspace().getName()); Node tx1 = s1.getRootNode().getNode("pretx").addNode("tx1"); Node tx2 = s2.getRootNode().getNode("pretx").addNode("tx2"); // keep this change out of the current Tx, this is necessary since // we have now auto-enlistment mechanism that is triggered at session save Transaction tx = txService.getTransactionManager().suspend(); s0.save(); // save that parent of tx1 removed txService.getTransactionManager().resume(tx); s1.save(); s2.save(); try { ut.commit(); // internally XAException should be thrown fail("Exception should occurs"); } catch (Exception e) { // ok } s1.logout(); s2.logout(); try { session.getItem("/pretx/tx1"); fail("PathNotFoundException should be thrown"); } catch (PathNotFoundException e) { // ok } } public void testSetRollbackOnly() throws Exception { assertNotNull(txService); UserTransaction ut = txService.getUserTransaction(); ut.begin(); // we need to create the session within the transaction to ensure that it will be enlisted Session session = repository.login(credentials, "ws"); session.getRootNode().addNode("txrollback"); ut.setRollbackOnly(); try { session.save(); fail("IllegalStateException should have be thrown as a save is forbidden after a setRollbackOnly"); } catch (IllegalStateException e) { } try { assertNotNull(session.getItem("/txrollback")); fail("PathNotFoundException should have be thrown"); } catch (PathNotFoundException e) { } ut.rollback(); try { assertNotNull(session.getItem("/txrollback")); fail("PathNotFoundException should have be thrown"); } catch (PathNotFoundException e) { } } }