diff --git a/jpos/src/main/java/org/jpos/transaction/TransactionManager.java b/jpos/src/main/java/org/jpos/transaction/TransactionManager.java index 635202facc..2a3946b3eb 100644 --- a/jpos/src/main/java/org/jpos/transaction/TransactionManager.java +++ b/jpos/src/main/java/org/jpos/transaction/TransactionManager.java @@ -82,6 +82,7 @@ public class TransactionManager boolean profiler; boolean doRecover; boolean callSelectorOnAbort; + boolean abortOnMisconfiguredGroups; int sessions; int maxSessions; int threshold; @@ -450,6 +451,7 @@ public void setConfiguration (Configuration cfg) callSelectorOnAbort = cfg.getBoolean("call-selector-on-abort", true); if (profiler) metrics = new Metrics(new AtomicHistogram(cfg.getLong("metrics-highest-trackable-value", 60000), 2)); + abortOnMisconfiguredGroups = cfg.getBoolean("abort-on-misconfigured-groups"); } public void addListener (TransactionStatusListener l) { synchronized (statusListeners) { @@ -691,8 +693,11 @@ session, TransactionStatusEvent.State.PREPARING, id, getName(p), context while (st.hasMoreTokens ()) { String grp = st.nextToken(); addGroup (id, grp); - if (evt != null && groups.get(grp) == null) + if (evt != null && groups.get(grp) == null) { evt.addMessage (" WARNING: group '" + grp + "' not configured"); + if (abortOnMisconfiguredGroups) + abort = true; + } participants.addAll (getParticipants (grp)); } while (iter.hasNext()) diff --git a/jpos/src/test/java/org/jpos/transaction/TransactionManagerTest.java b/jpos/src/test/java/org/jpos/transaction/TransactionManagerTest.java index 769e62602f..67417e9a25 100644 --- a/jpos/src/test/java/org/jpos/transaction/TransactionManagerTest.java +++ b/jpos/src/test/java/org/jpos/transaction/TransactionManagerTest.java @@ -20,6 +20,7 @@ import static org.apache.commons.lang3.JavaVersion.JAVA_14; import static org.apache.commons.lang3.SystemUtils.isJavaVersionAtMost; +import static org.jpos.transaction.TransactionConstants.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -27,15 +28,12 @@ import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.*; -import java.io.File; -import java.io.IOException; -import java.io.NotActiveException; -import java.io.SerializablePermission; -import java.io.UnsupportedEncodingException; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.List; +import java.io.*; +import java.util.*; import org.jdom2.Comment; import org.jdom2.Element; @@ -43,6 +41,7 @@ import org.jpos.core.ConfigurationException; import org.jpos.core.SimpleConfiguration; import org.jpos.core.SubConfiguration; +import org.jpos.space.SpaceFactory; import org.jpos.transaction.participant.BSHTransactionParticipant; import org.jpos.transaction.participant.CheckPoint; import org.jpos.transaction.participant.Debug; @@ -453,7 +452,58 @@ public void testPrepare8() throws Throwable { LogEvent evt = new LogEvent(); int result = transactionManager.prepare(1, 100L, Boolean.TRUE, new ArrayList(), arrayList.iterator(), false, evt, null); assertEquals(3, evt.getPayLoad().size(), "evt.payLoad.size()"); - assertEquals(TransactionConstants.PREPARED, result, "result"); + assertEquals(PREPARED, result, "result"); + } + + @Test + public void testPrepareAbortsOnMisconfiguredGroup() throws Throwable { + transactionManager = new TransactionManager(); + transactionManager.psp = SpaceFactory.getSpace(); + transactionManager.groups = Collections.emptyMap(); + transactionManager.abortOnMisconfiguredGroups = true; + transactionManager.setName(transactionManager.getClass().getSimpleName()); + + TransactionParticipant participant = mock(TransactionParticipant.class); + when(participant.prepare(anyLong(), any())).thenReturn(PREPARED | NO_JOIN); + + GroupSelector selector = mock(GroupSelector.class); + when(selector.prepare(anyLong(), any())).thenReturn(PREPARED | NO_JOIN); + when(selector.select(anyLong(), any())).thenReturn("Lorem ipsum dolor sit amet"); + + List list = Arrays.asList(participant, selector); + LogEvent evt = new LogEvent(); + + int result = transactionManager.prepare(1, 100L, Boolean.FALSE, members, list.iterator(), false, evt, null); + + verify(participant, times(1)).prepare(anyLong(), any()); + verify(selector, times(1)).prepare(anyLong(), any()); + verify(selector, times(1)).select(anyLong(), any()); + assertEquals(ABORTED, result); + } + + @Test + public void testPrepareShouldNotAbortOnMisconfiguredGroupByDefault() throws Throwable { + transactionManager = new TransactionManager(); + transactionManager.psp = SpaceFactory.getSpace(); + transactionManager.groups = Collections.emptyMap(); + transactionManager.setName(transactionManager.getClass().getSimpleName()); + + TransactionParticipant participant = mock(TransactionParticipant.class); + when(participant.prepare(anyLong(), any())).thenReturn(PREPARED); + + GroupSelector selector = mock(GroupSelector.class); + when(selector.prepare(anyLong(), any())).thenReturn(PREPARED); + when(selector.select(anyLong(), any())).thenReturn("Lorem ipsum dolor sit amet"); + + List list = Arrays.asList(participant, selector); + LogEvent evt = new LogEvent(); + + int result = transactionManager.prepare(1, 100L, Boolean.FALSE, members, list.iterator(), false, evt, null); + + verify(participant, times(1)).prepare(anyLong(), any()); + verify(selector, times(1)).prepare(anyLong(), any()); + verify(selector, times(1)).select(anyLong(), any()); + assertEquals(PREPARED, result); } @Test