Search in sources :

Example 1 with StateMachineConfig

use of org.killbill.automaton.StateMachineConfig in project killbill by killbill.

the class TestStateMachineConfigCache method testExistingTenantStateMachineConfig.

@Test(groups = "fast")
public void testExistingTenantStateMachineConfig() throws PaymentApiException, URISyntaxException, IOException {
    final String pluginName = UUID.randomUUID().toString();
    final InternalCallContext differentMultiTenantContext = Mockito.mock(InternalCallContext.class);
    Mockito.when(differentMultiTenantContext.getTenantRecordId()).thenReturn(55667788L);
    final AtomicBoolean shouldThrow = new AtomicBoolean(false);
    final Long multiTenantRecordId = multiTenantContext.getTenantRecordId();
    final Long otherMultiTenantRecordId = otherMultiTenantContext.getTenantRecordId();
    Mockito.when(tenantInternalApi.getPluginPaymentStateMachineConfig(Mockito.eq(pluginName), Mockito.any(InternalTenantContext.class))).thenAnswer(new Answer<String>() {

        @Override
        public String answer(final InvocationOnMock invocation) throws Throwable {
            if (shouldThrow.get()) {
                throw new RuntimeException();
            }
            final InternalTenantContext internalContext = (InternalTenantContext) invocation.getArguments()[1];
            if (multiTenantRecordId.equals(internalContext.getTenantRecordId())) {
                return new String(ByteStreams.toByteArray(UriAccessor.accessUri(Resources.getResource(PaymentModule.DEFAULT_STATE_MACHINE_PAYMENT_XML).toExternalForm())));
            } else if (otherMultiTenantRecordId.equals(internalContext.getTenantRecordId())) {
                return new String(ByteStreams.toByteArray(UriAccessor.accessUri(Resources.getResource(PaymentModule.DEFAULT_STATE_MACHINE_RETRY_XML).toExternalForm())));
            } else {
                return null;
            }
        }
    });
    // Verify the lookup for a non-cached tenant. No system config is set yet but EhCacheStateMachineConfigCache returns a default empty one
    final StateMachineConfig defaultStateMachineConfig = stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, differentMultiTenantContext);
    Assert.assertNotNull(defaultStateMachineConfig);
    // Make sure the cache loader isn't invoked, see https://github.com/killbill/killbill/issues/300
    shouldThrow.set(true);
    final StateMachineConfig defaultStateMachineConfig2 = stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, differentMultiTenantContext);
    Assert.assertNotNull(defaultStateMachineConfig2);
    Assert.assertEquals(defaultStateMachineConfig2, defaultStateMachineConfig);
    shouldThrow.set(false);
    // Verify the lookup for this tenant
    Assert.assertEquals(stateMachineConfigCache.getPaymentStateMachineConfig(UUID.randomUUID().toString(), multiTenantContext), defaultStateMachineConfig);
    final StateMachineConfig result = stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, multiTenantContext);
    Assert.assertNotNull(result);
    Assert.assertNotEquals(result, defaultStateMachineConfig);
    Assert.assertEquals(result.getStateMachines().length, 8);
    // Verify the lookup for another tenant
    Assert.assertEquals(stateMachineConfigCache.getPaymentStateMachineConfig(UUID.randomUUID().toString(), otherMultiTenantContext), defaultStateMachineConfig);
    final StateMachineConfig otherResult = stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, otherMultiTenantContext);
    Assert.assertNotNull(otherResult);
    Assert.assertEquals(otherResult.getStateMachines().length, 1);
    shouldThrow.set(true);
    // Verify the lookup for this tenant
    Assert.assertEquals(stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, multiTenantContext), result);
    // Verify the lookup with another context for the same tenant
    final InternalCallContext sameMultiTenantContext = Mockito.mock(InternalCallContext.class);
    Mockito.when(sameMultiTenantContext.getAccountRecordId()).thenReturn(9102L);
    Mockito.when(sameMultiTenantContext.getTenantRecordId()).thenReturn(multiTenantRecordId);
    Assert.assertEquals(stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, sameMultiTenantContext), result);
    // Verify the lookup with the other tenant
    Assert.assertEquals(stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, otherMultiTenantContext), otherResult);
    // Verify clearing the cache works
    stateMachineConfigCache.clearPaymentStateMachineConfig(pluginName, multiTenantContext);
    Assert.assertEquals(stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, otherMultiTenantContext), otherResult);
    try {
        stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, multiTenantContext);
        Assert.fail();
    } catch (final CacheException exception) {
        Assert.assertTrue(exception.getCause() instanceof RuntimeException);
    }
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CacheException(net.sf.ehcache.CacheException) InternalTenantContext(org.killbill.billing.callcontext.InternalTenantContext) InvocationOnMock(org.mockito.invocation.InvocationOnMock) StateMachineConfig(org.killbill.automaton.StateMachineConfig) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) Test(org.testng.annotations.Test)

Example 2 with StateMachineConfig

use of org.killbill.automaton.StateMachineConfig in project killbill by killbill.

the class EhCacheStateMachineConfigCache method getPaymentStateMachineConfig.

@Override
public StateMachineConfig getPaymentStateMachineConfig(final String pluginName, final InternalTenantContext tenantContext) throws PaymentApiException {
    if (tenantContext.getTenantRecordId() == InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID || cacheController == null) {
        return defaultPaymentStateMachineConfig;
    }
    final String pluginConfigKey = getCacheKeyName(pluginName, tenantContext);
    final CacheLoaderArgument cacheLoaderArgument = createCacheLoaderArgument(pluginName);
    try {
        StateMachineConfig pluginPaymentStateMachineConfig = (StateMachineConfig) cacheController.get(pluginConfigKey, cacheLoaderArgument);
        // It means we are using the default state machine config in a multi-tenant deployment
        if (pluginPaymentStateMachineConfig == null) {
            pluginPaymentStateMachineConfig = defaultPaymentStateMachineConfig;
            cacheController.add(pluginConfigKey, pluginPaymentStateMachineConfig);
        }
        return pluginPaymentStateMachineConfig;
    } catch (final IllegalStateException e) {
        // TODO 0.17 proper error code
        throw new PaymentApiException(e, ErrorCode.PAYMENT_INTERNAL_ERROR, "Invalid payment state machine");
    }
}
Also used : StateMachineConfig(org.killbill.automaton.StateMachineConfig) DefaultStateMachineConfig(org.killbill.automaton.DefaultStateMachineConfig) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) CacheLoaderArgument(org.killbill.billing.util.cache.CacheLoaderArgument)

Example 3 with StateMachineConfig

use of org.killbill.automaton.StateMachineConfig in project killbill by killbill.

the class PaymentAutomatonRunner method runStateMachineOperation.

private void runStateMachineOperation(final String initialStateName, final TransactionType transactionType, final LeavingStateCallback leavingStateCallback, final OperationCallback operationCallback, final EnteringStateCallback enteringStateCallback, final Boolean includeDeletedPaymentMethod, final PaymentStateContext paymentStateContext, final PaymentAutomatonDAOHelper daoHelper) throws PaymentApiException {
    try {
        final StateMachineConfig stateMachineConfig = paymentSMHelper.getStateMachineConfig(daoHelper.getPaymentProviderPluginName(includeDeletedPaymentMethod), paymentStateContext.getInternalCallContext());
        final StateMachine initialStateMachine = stateMachineConfig.getStateMachineForState(initialStateName);
        final State initialState = initialStateMachine.getState(initialStateName);
        final Operation operation = paymentSMHelper.getOperationForTransaction(stateMachineConfig, transactionType);
        initialState.runOperation(operation, operationCallback, enteringStateCallback, leavingStateCallback);
    } catch (final MissingEntryException e) {
        throw new PaymentApiException(e.getCause(), ErrorCode.PAYMENT_INVALID_OPERATION, transactionType, initialStateName);
    } catch (final OperationException e) {
        if (e.getCause() == null) {
            throw new PaymentApiException(e, ErrorCode.PAYMENT_INTERNAL_ERROR, MoreObjects.firstNonNull(e.getMessage(), ""));
        } else if (e.getCause() instanceof PaymentApiException) {
            throw (PaymentApiException) e.getCause();
        } else {
            throw new PaymentApiException(e.getCause(), ErrorCode.PAYMENT_INTERNAL_ERROR, MoreObjects.firstNonNull(e.getMessage(), ""));
        }
    }
}
Also used : StateMachine(org.killbill.automaton.StateMachine) State(org.killbill.automaton.State) StateMachineConfig(org.killbill.automaton.StateMachineConfig) MissingEntryException(org.killbill.automaton.MissingEntryException) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) PurchaseOperation(org.killbill.billing.payment.core.sm.payments.PurchaseOperation) RefundOperation(org.killbill.billing.payment.core.sm.payments.RefundOperation) AuthorizeOperation(org.killbill.billing.payment.core.sm.payments.AuthorizeOperation) VoidOperation(org.killbill.billing.payment.core.sm.payments.VoidOperation) Operation(org.killbill.automaton.Operation) CreditOperation(org.killbill.billing.payment.core.sm.payments.CreditOperation) ChargebackOperation(org.killbill.billing.payment.core.sm.payments.ChargebackOperation) CaptureOperation(org.killbill.billing.payment.core.sm.payments.CaptureOperation) OperationException(org.killbill.automaton.OperationException)

Example 4 with StateMachineConfig

use of org.killbill.automaton.StateMachineConfig in project killbill by killbill.

the class TestStateMachineProvider method testStateMachineProvider.

@Test(groups = "fast", description = "https://github.com/killbill/killbill/issues/226")
public void testStateMachineProvider() throws Exception {
    final StateMachineProvider retryStateMachineProvider = new StateMachineProvider(PaymentModule.DEFAULT_STATE_MACHINE_RETRY_XML);
    final StateMachineConfig retryStateMachineConfig = retryStateMachineProvider.get();
    Assert.assertEquals(retryStateMachineConfig.getStateMachines().length, 1);
    final StateMachineProvider paymentStateMachineProvider = new StateMachineProvider(PaymentModule.DEFAULT_STATE_MACHINE_PAYMENT_XML);
    final StateMachineConfig paymentStateMachineConfig = paymentStateMachineProvider.get();
    Assert.assertEquals(paymentStateMachineConfig.getStateMachines().length, 8);
}
Also used : StateMachineProvider(org.killbill.billing.payment.glue.PaymentModule.StateMachineProvider) StateMachineConfig(org.killbill.automaton.StateMachineConfig) Test(org.testng.annotations.Test)

Example 5 with StateMachineConfig

use of org.killbill.automaton.StateMachineConfig in project killbill by killbill.

the class TestStateMachineConfigCacheInvalidationCallback method testInvalidation.

@Test(groups = "fast")
public void testInvalidation() throws Exception {
    final String pluginName = UUID.randomUUID().toString();
    final StateMachineConfig defaultPaymentStateMachineConfig = stateMachineConfigCache.getPaymentStateMachineConfig(UUID.randomUUID().toString(), internalCallContext);
    Assert.assertNotNull(defaultPaymentStateMachineConfig);
    final AtomicBoolean shouldThrow = new AtomicBoolean(false);
    Mockito.when(tenantInternalApi.getPluginPaymentStateMachineConfig(Mockito.eq(pluginName), Mockito.any(InternalTenantContext.class))).thenAnswer(new Answer<String>() {

        @Override
        public String answer(final InvocationOnMock invocation) throws Throwable {
            if (shouldThrow.get()) {
                throw new RuntimeException();
            }
            return null;
        }
    });
    // Prime caches
    Assert.assertEquals(stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, internalCallContext), defaultPaymentStateMachineConfig);
    Assert.assertEquals(stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, otherMultiTenantContext), defaultPaymentStateMachineConfig);
    shouldThrow.set(true);
    // No exception (cached)
    Assert.assertEquals(stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, internalCallContext), defaultPaymentStateMachineConfig);
    cacheInvalidationCallback.invalidateCache(TenantKey.PLUGIN_PAYMENT_STATE_MACHINE_, pluginName, multiTenantContext);
    try {
        stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, multiTenantContext);
        Assert.fail();
    } catch (final CacheException exception) {
        Assert.assertTrue(exception.getCause() instanceof RuntimeException);
    }
    // No exception (cached)
    Assert.assertEquals(stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, otherMultiTenantContext), defaultPaymentStateMachineConfig);
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CacheException(net.sf.ehcache.CacheException) InternalTenantContext(org.killbill.billing.callcontext.InternalTenantContext) InvocationOnMock(org.mockito.invocation.InvocationOnMock) StateMachineConfig(org.killbill.automaton.StateMachineConfig) Test(org.testng.annotations.Test)

Aggregations

StateMachineConfig (org.killbill.automaton.StateMachineConfig)5 Test (org.testng.annotations.Test)3 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)2 CacheException (net.sf.ehcache.CacheException)2 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)2 PaymentApiException (org.killbill.billing.payment.api.PaymentApiException)2 InvocationOnMock (org.mockito.invocation.InvocationOnMock)2 DefaultStateMachineConfig (org.killbill.automaton.DefaultStateMachineConfig)1 MissingEntryException (org.killbill.automaton.MissingEntryException)1 Operation (org.killbill.automaton.Operation)1 OperationException (org.killbill.automaton.OperationException)1 State (org.killbill.automaton.State)1 StateMachine (org.killbill.automaton.StateMachine)1 InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)1 AuthorizeOperation (org.killbill.billing.payment.core.sm.payments.AuthorizeOperation)1 CaptureOperation (org.killbill.billing.payment.core.sm.payments.CaptureOperation)1 ChargebackOperation (org.killbill.billing.payment.core.sm.payments.ChargebackOperation)1 CreditOperation (org.killbill.billing.payment.core.sm.payments.CreditOperation)1 PurchaseOperation (org.killbill.billing.payment.core.sm.payments.PurchaseOperation)1 RefundOperation (org.killbill.billing.payment.core.sm.payments.RefundOperation)1