killbill-aplcache
Changes
account/pom.xml 2(+1 -1)
api/pom.xml 2(+1 -1)
beatrix/pom.xml 2(+1 -1)
beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestCatalogRetireElements.java 9(+3 -6)
catalog/pom.xml 2(+1 -1)
currency/pom.xml 2(+1 -1)
entitlement/pom.xml 2(+1 -1)
invoice/pom.xml 2(+1 -1)
jaxrs/pom.xml 2(+1 -1)
junction/pom.xml 2(+1 -1)
NEWS 4(+4 -0)
overdue/pom.xml 2(+1 -1)
payment/pom.xml 2(+1 -1)
pom.xml 2(+1 -1)
profiles/killbill/pom.xml 2(+1 -1)
profiles/killpay/pom.xml 2(+1 -1)
profiles/pom.xml 2(+1 -1)
subscription/pom.xml 2(+1 -1)
subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java 51(+28 -23)
subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java 33(+24 -9)
subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java 13(+13 -0)
subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java 2(+2 -0)
subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java 5(+5 -0)
tenant/pom.xml 2(+1 -1)
usage/pom.xml 2(+1 -1)
util/pom.xml 2(+1 -1)
Details
account/pom.xml 2(+1 -1)
diff --git a/account/pom.xml b/account/pom.xml
index 3381927..417f676 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-account</artifactId>
api/pom.xml 2(+1 -1)
diff --git a/api/pom.xml b/api/pom.xml
index c7a0a58..cd2c6d5 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-internal-api</artifactId>
beatrix/pom.xml 2(+1 -1)
diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index 13276df..61adc18 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-beatrix</artifactId>
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestCatalogRetireElements.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestCatalogRetireElements.java
index 0f3c7e1..965a5fb 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestCatalogRetireElements.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestCatalogRetireElements.java
@@ -53,8 +53,7 @@ public class TestCatalogRetireElements extends TestIntegrationBase {
return super.getConfigSource("/beatrixCatalogRetireElements.properties");
}
- // Flaky, see https://github.com/killbill/killbill/issues/860
- @Test(groups = "slow", retryAnalyzer = FlakyRetryAnalyzer.class)
+ @Test(groups = "slow")
public void testRetirePlan() throws Exception {
// Catalog v1 starts in 2011-01-01
// Catalog v2 starts in 2015-12-01
@@ -111,8 +110,7 @@ public class TestCatalogRetireElements extends TestIntegrationBase {
}
- // Flaky, see https://github.com/killbill/killbill/issues/860
- @Test(groups = "slow", retryAnalyzer = FlakyRetryAnalyzer.class)
+ @Test(groups = "slow")
public void testRetirePlanWithUncancel() throws Exception {
// Catalog v1 starts in 2011-01-01
// Catalog v2 starts in 2015-12-01
@@ -176,8 +174,7 @@ public class TestCatalogRetireElements extends TestIntegrationBase {
}
}
- // Flaky, see https://github.com/killbill/killbill/issues/860
- @Test(groups = "slow", retryAnalyzer = FlakyRetryAnalyzer.class)
+ @Test(groups = "slow")
public void testRetirePlanAfterChange() throws Exception {
// Catalog v1 starts in 2011-01-01
// Catalog v3 starts in 2016-01-01
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationBase.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationBase.java
index 4e8ecce..33fe5ab 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationBase.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationBase.java
@@ -308,6 +308,11 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
public void beforeClass() throws Exception {
final InvoiceConfig defaultInvoiceConfig = new ConfigurationObjectFactory(skifeConfigSource).build(InvoiceConfig.class);
invoiceConfig = new ConfigurableInvoiceConfig(defaultInvoiceConfig);
+ // The default value is 50, i.e. wait 50 x 100ms = 5s to get the lock. This isn't always enough and can lead to random tests failures
+ // in the listener status: after moving the clock, if there are two notifications triggering an invoice run, we typically expect
+ // both an INVOICE and a NULL_INVOICE event. If the invoice generation takes too long, the NULL_INVOICE event is never generated
+ // (LockFailedException): the test itself doesn't fail (the correct invoice is generated), but assertListenerStatus() would.
+ invoiceConfig.setMaxGlobalLockRetries(150);
final Injector g = Guice.createInjector(Stage.PRODUCTION, new BeatrixIntegrationModule(configSource, invoiceConfig));
g.injectMembers(this);
}
@@ -973,10 +978,12 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
private final InvoiceConfig defaultInvoiceConfig;
+ private int maxGlobalLockRetries;
private boolean isInvoicingSystemEnabled;
public ConfigurableInvoiceConfig(final InvoiceConfig defaultInvoiceConfig) {
this.defaultInvoiceConfig = defaultInvoiceConfig;
+ maxGlobalLockRetries = defaultInvoiceConfig.getMaxGlobalLockRetries();
isInvoicingSystemEnabled = defaultInvoiceConfig.isInvoicingSystemEnabled();
}
@@ -1032,7 +1039,7 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
@Override
public int getMaxGlobalLockRetries() {
- return defaultInvoiceConfig.getMaxGlobalLockRetries();
+ return maxGlobalLockRetries;
}
@Override
@@ -1080,6 +1087,10 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
return getItemResultBehaviorMode();
}
+ public void setMaxGlobalLockRetries(final int maxGlobalLockRetries) {
+ this.maxGlobalLockRetries = maxGlobalLockRetries;
+ }
+
public void setInvoicingSystemEnabled(final boolean invoicingSystemEnabled) {
isInvoicingSystemEnabled = invoicingSystemEnabled;
}
catalog/pom.xml 2(+1 -1)
diff --git a/catalog/pom.xml b/catalog/pom.xml
index f6e5a11..abb51d5 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-catalog</artifactId>
currency/pom.xml 2(+1 -1)
diff --git a/currency/pom.xml b/currency/pom.xml
index efb61bd..62792ff 100644
--- a/currency/pom.xml
+++ b/currency/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-currency</artifactId>
entitlement/pom.xml 2(+1 -1)
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index 4549ace..ee7964e 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-entitlement</artifactId>
invoice/pom.xml 2(+1 -1)
diff --git a/invoice/pom.xml b/invoice/pom.xml
index c52b20c..d86d45c 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-invoice</artifactId>
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/InvoicePluginDispatcher.java b/invoice/src/main/java/org/killbill/billing/invoice/InvoicePluginDispatcher.java
index d170b10..c46b094 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/InvoicePluginDispatcher.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/InvoicePluginDispatcher.java
@@ -176,7 +176,7 @@ public class InvoicePluginDispatcher {
final InvoiceItem sanitizedInvoiceItem = validateAndSanitizeInvoiceItemFromPlugin(originalInvoice, additionalInvoiceItem, invoicePlugin);
additionalInvoiceItems.add(sanitizedInvoiceItem);
}
- invoiceUpdated = invoiceUpdated || updateOriginalInvoiceWithPluginInvoiceItems(originalInvoice, additionalInvoiceItems);
+ invoiceUpdated = updateOriginalInvoiceWithPluginInvoiceItems(originalInvoice, additionalInvoiceItems) || invoiceUpdated;
}
}
jaxrs/pom.xml 2(+1 -1)
diff --git a/jaxrs/pom.xml b/jaxrs/pom.xml
index 764f7ee..335c64a 100644
--- a/jaxrs/pom.xml
+++ b/jaxrs/pom.xml
@@ -21,7 +21,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-jaxrs</artifactId>
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
index fed1361..e966a1a 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
@@ -632,10 +632,6 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
}
}
- protected void verifyNumberOfElements(int actual, int expected, String errorMessage) {
- Preconditions.checkArgument(actual == expected, errorMessage);
- }
-
protected void logDeprecationParameterWarningIfNeeded(@Nullable final String deprecatedParam, final String... replacementParams) {
if (deprecatedParam != null) {
log.warn(String.format("Parameter %s is being deprecated: Instead use parameters %s", deprecatedParam, Joiner.on(",").join(replacementParams)));
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java
index 92253cc..ad5d2db 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java
@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeoutException;
+import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -105,6 +106,7 @@ import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
@@ -328,8 +330,8 @@ public class SubscriptionResource extends JaxRsResourceBase {
final Account account = accountUserApi.getAccountById(entitlementsWithAddOns.get(0).getBaseEntitlementAndAddOns().get(0).getAccountId(), callContext);
- final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
- for (BulkSubscriptionsBundleJson bulkBaseEntitlementWithAddOns : entitlementsWithAddOns) {
+ final Collection<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
+ for (final BulkSubscriptionsBundleJson bulkBaseEntitlementWithAddOns : entitlementsWithAddOns) {
final Iterable<SubscriptionJson> baseEntitlements = Iterables.filter(
bulkBaseEntitlementWithAddOns.getBaseEntitlementAndAddOns(), new Predicate<SubscriptionJson>() {
@Override
@@ -337,26 +339,44 @@ public class SubscriptionResource extends JaxRsResourceBase {
return ProductCategory.BASE.equals(subscription.getProductCategory());
}
});
- Preconditions.checkArgument(Iterables.size(baseEntitlements) > 0, "SubscriptionJson Base Entitlement needs to be provided");
- verifyNumberOfElements(Iterables.size(baseEntitlements), 1, "Only one BASE product is allowed per bundle.");
- final SubscriptionJson baseEntitlement = baseEntitlements.iterator().next();
- final Iterable<SubscriptionJson> addonEntitlements = Iterables.filter(
- bulkBaseEntitlementWithAddOns.getBaseEntitlementAndAddOns(), new Predicate<SubscriptionJson>() {
- @Override
- public boolean apply(final SubscriptionJson subscription) {
- return ProductCategory.ADD_ON.equals(subscription.getProductCategory());
- }
- }
- );
-
- final List<EntitlementSpecifier> entitlementSpecifierList = buildEntitlementSpecifierList(baseEntitlement, addonEntitlements, account.getCurrency());
+ final List<EntitlementSpecifier> entitlementSpecifierList;
+ final String bundleExternalKey;
+ if (baseEntitlements.iterator().hasNext()) {
+ Preconditions.checkArgument(Iterables.size(baseEntitlements) == 1, "Only one BASE product is allowed per bundle.");
+
+ final SubscriptionJson baseEntitlement = baseEntitlements.iterator().next();
+ final Iterable<SubscriptionJson> addonEntitlements = Iterables.filter(bulkBaseEntitlementWithAddOns.getBaseEntitlementAndAddOns(),
+ new Predicate<SubscriptionJson>() {
+ @Override
+ public boolean apply(final SubscriptionJson subscription) {
+ return ProductCategory.ADD_ON.equals(subscription.getProductCategory());
+ }
+ });
+
+ entitlementSpecifierList = buildEntitlementSpecifierList(baseEntitlement, addonEntitlements, account.getCurrency());
+ bundleExternalKey = baseEntitlement.getExternalKey();
+ } else {
+ final Collection<SubscriptionJson> standaloneEntitlements = Collections2.filter(bulkBaseEntitlementWithAddOns.getBaseEntitlementAndAddOns(),
+ new Predicate<SubscriptionJson>() {
+ @Override
+ public boolean apply(final SubscriptionJson subscription) {
+ return ProductCategory.STANDALONE.equals(subscription.getProductCategory());
+ }
+ });
+ entitlementSpecifierList = buildEntitlementSpecifierList(standaloneEntitlements, account.getCurrency());
+ bundleExternalKey = standaloneEntitlements.isEmpty() ? null : standaloneEntitlements.iterator().next().getExternalKey();
+ }
// create the baseEntitlementSpecifierWithAddOns
final LocalDate resolvedEntitlementDate = requestedDate != null ? toLocalDate(requestedDate) : toLocalDate(entitlementDate);
final LocalDate resolvedBillingDate = requestedDate != null ? toLocalDate(requestedDate) : toLocalDate(billingDate);
- final BaseEntitlementWithAddOnsSpecifier baseEntitlementSpecifierWithAddOns = buildBaseEntitlementWithAddOnsSpecifier(entitlementSpecifierList, resolvedEntitlementDate, resolvedBillingDate, null, baseEntitlement, isMigrated);
+ final BaseEntitlementWithAddOnsSpecifier baseEntitlementSpecifierWithAddOns = buildBaseEntitlementWithAddOnsSpecifier(entitlementSpecifierList,
+ resolvedEntitlementDate,
+ resolvedBillingDate,
+ bundleExternalKey,
+ isMigrated);
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementSpecifierWithAddOns);
}
@@ -398,36 +418,14 @@ public class SubscriptionResource extends JaxRsResourceBase {
}
private List<EntitlementSpecifier> buildEntitlementSpecifierList(final SubscriptionJson baseEntitlement,
- final Iterable<SubscriptionJson> addonEntitlements, final Currency currency) {
+ final Iterable<SubscriptionJson> addonEntitlements,
+ final Currency currency) {
final List<EntitlementSpecifier> entitlementSpecifierList = new ArrayList<EntitlementSpecifier>();
//
- // BASE is fully specified we can add it
+ // BASE or STANDALONE is fully specified, we can add it
//
- if (baseEntitlement.getPlanName() != null ||
- (baseEntitlement.getProductName() != null &&
- baseEntitlement.getProductCategory() != null &&
- baseEntitlement.getBillingPeriod() != null &&
- baseEntitlement.getPriceList() != null)) {
- final PlanPhaseSpecifier planPhaseSpecifier = baseEntitlement.getPlanName() != null ?
- new PlanPhaseSpecifier(baseEntitlement.getPlanName(), null) :
- new PlanPhaseSpecifier(baseEntitlement.getProductName(),
- baseEntitlement.getBillingPeriod(), baseEntitlement.getPriceList(), null);
- final List<PlanPhasePriceOverride> overrides = PhasePriceOverrideJson.toPlanPhasePriceOverrides(baseEntitlement.getPriceOverrides(), planPhaseSpecifier, currency);
-
- EntitlementSpecifier specifier = new EntitlementSpecifier() {
- @Override
- public PlanPhaseSpecifier getPlanPhaseSpecifier() {
- return planPhaseSpecifier;
- }
-
- @Override
- public List<PlanPhasePriceOverride> getOverrides() {
- return overrides;
- }
- };
- entitlementSpecifierList.add(specifier);
- }
+ buildEntitlementSpecifier(baseEntitlement, currency, entitlementSpecifierList);
for (final SubscriptionJson entitlement : addonEntitlements) {
// verifications
@@ -439,38 +437,79 @@ public class SubscriptionResource extends JaxRsResourceBase {
entitlement.getPriceList(), "SubscriptionJson priceList needs to be set for each element");
}
// create the entitlementSpecifier
- final PlanPhaseSpecifier planPhaseSpecifier = entitlement.getPlanName() != null ?
- new PlanPhaseSpecifier(entitlement.getPlanName(), null) :
- new PlanPhaseSpecifier(entitlement.getProductName(),
- entitlement.getBillingPeriod(), entitlement.getPriceList(), null);
- final List<PlanPhasePriceOverride> overrides = PhasePriceOverrideJson.toPlanPhasePriceOverrides(entitlement.getPriceOverrides(), planPhaseSpecifier, currency);
-
- EntitlementSpecifier specifier = new EntitlementSpecifier() {
- @Override
- public PlanPhaseSpecifier getPlanPhaseSpecifier() {
- return planPhaseSpecifier;
- }
+ buildEntitlementSpecifier(entitlement, currency, entitlementSpecifierList);
+ }
+ return entitlementSpecifierList;
+ }
- @Override
- public List<PlanPhasePriceOverride> getOverrides() {
- return overrides;
- }
- };
- entitlementSpecifierList.add(specifier);
+ private List<EntitlementSpecifier> buildEntitlementSpecifierList(final Iterable<SubscriptionJson> standaloneEntitlements,
+ final Currency currency) {
+ final List<EntitlementSpecifier> entitlementSpecifierList = new ArrayList<EntitlementSpecifier>();
+
+ for (final SubscriptionJson standaloneEntitlement : standaloneEntitlements) {
+ // verifications
+ verifyNonNullOrEmpty(standaloneEntitlement, "SubscriptionJson body should be specified for each element");
+ if (standaloneEntitlement.getPlanName() == null) {
+ verifyNonNullOrEmpty(standaloneEntitlement.getProductName(), "SubscriptionJson productName needs to be set for each element",
+ standaloneEntitlement.getProductCategory(), "SubscriptionJson productCategory needs to be set for each element",
+ standaloneEntitlement.getBillingPeriod(), "SubscriptionJson billingPeriod needs to be set for each element",
+ standaloneEntitlement.getPriceList(), "SubscriptionJson priceList needs to be set for each element");
+ }
+ // create the entitlementSpecifier
+ buildEntitlementSpecifier(standaloneEntitlement, currency, entitlementSpecifierList);
}
return entitlementSpecifierList;
}
- private BaseEntitlementWithAddOnsSpecifier buildBaseEntitlementWithAddOnsSpecifier(final List<EntitlementSpecifier> entitlementSpecifierList, final LocalDate resolvedEntitlementDate, final LocalDate resolvedBillingDate, final UUID bundleId, final SubscriptionJson baseEntitlement, final @QueryParam(QUERY_MIGRATED) @DefaultValue("false") Boolean isMigrated) {
+ private void buildEntitlementSpecifier(final SubscriptionJson subscriptionJson,
+ final Currency currency,
+ final Collection<EntitlementSpecifier> entitlementSpecifierList) {
+ if (subscriptionJson.getPlanName() == null &&
+ (subscriptionJson.getProductName() == null ||
+ subscriptionJson.getProductCategory() == null ||
+ subscriptionJson.getBillingPeriod() == null ||
+ subscriptionJson.getPriceList() == null)) {
+ return;
+ }
+
+ final PlanPhaseSpecifier planPhaseSpecifier = subscriptionJson.getPlanName() != null ?
+ new PlanPhaseSpecifier(subscriptionJson.getPlanName(), null) :
+ new PlanPhaseSpecifier(subscriptionJson.getProductName(),
+ subscriptionJson.getBillingPeriod(),
+ subscriptionJson.getPriceList(),
+ null);
+ final List<PlanPhasePriceOverride> overrides = PhasePriceOverrideJson.toPlanPhasePriceOverrides(subscriptionJson.getPriceOverrides(),
+ planPhaseSpecifier,
+ currency);
+
+ final EntitlementSpecifier specifier = new EntitlementSpecifier() {
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifier() {
+ return planPhaseSpecifier;
+ }
+
+ @Override
+ public List<PlanPhasePriceOverride> getOverrides() {
+ return overrides;
+ }
+ };
+ entitlementSpecifierList.add(specifier);
+ }
+
+ private BaseEntitlementWithAddOnsSpecifier buildBaseEntitlementWithAddOnsSpecifier(final Iterable<EntitlementSpecifier> entitlementSpecifierList,
+ final LocalDate resolvedEntitlementDate,
+ final LocalDate resolvedBillingDate,
+ @Nullable final String bundleExternalKey,
+ final Boolean isMigrated) {
return new BaseEntitlementWithAddOnsSpecifier() {
@Override
public UUID getBundleId() {
- return bundleId;
+ return null;
}
@Override
public String getExternalKey() {
- return baseEntitlement.getExternalKey();
+ return bundleExternalKey;
}
@Override
junction/pom.xml 2(+1 -1)
diff --git a/junction/pom.xml b/junction/pom.xml
index 3d51db9..e861302 100644
--- a/junction/pom.xml
+++ b/junction/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-junction</artifactId>
NEWS 4(+4 -0)
diff --git a/NEWS b/NEWS
index b7c3775..cc38732 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+0.19.10
+ Entitlement and Subscription performance
+ Fix issue in invoice plugin ordering
+
0.19.9
Introduce thread-local dirty DB flag
Fix NPE in bus and notifications threads
overdue/pom.xml 2(+1 -1)
diff --git a/overdue/pom.xml b/overdue/pom.xml
index 0670da2..50e64d0 100644
--- a/overdue/pom.xml
+++ b/overdue/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-overdue</artifactId>
payment/pom.xml 2(+1 -1)
diff --git a/payment/pom.xml b/payment/pom.xml
index 8c33f57..66b0100 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-payment</artifactId>
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index 06735c7..0be4e28 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
<version>0.141.58</version>
</parent>
<artifactId>killbill</artifactId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<packaging>pom</packaging>
<name>killbill</name>
<description>Library for managing recurring subscriptions and the associated billing</description>
profiles/killbill/pom.xml 2(+1 -1)
diff --git a/profiles/killbill/pom.xml b/profiles/killbill/pom.xml
index 9f32ab1..df0486c 100644
--- a/profiles/killbill/pom.xml
+++ b/profiles/killbill/pom.xml
@@ -21,7 +21,7 @@
<parent>
<artifactId>killbill-profiles</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-profiles-killbill</artifactId>
profiles/killpay/pom.xml 2(+1 -1)
diff --git a/profiles/killpay/pom.xml b/profiles/killpay/pom.xml
index 6d90d6f..7bd7494 100644
--- a/profiles/killpay/pom.xml
+++ b/profiles/killpay/pom.xml
@@ -20,7 +20,7 @@
<parent>
<artifactId>killbill-profiles</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-profiles-killpay</artifactId>
profiles/pom.xml 2(+1 -1)
diff --git a/profiles/pom.xml b/profiles/pom.xml
index 355a94f..afe81c3 100644
--- a/profiles/pom.xml
+++ b/profiles/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-profiles</artifactId>
subscription/pom.xml 2(+1 -1)
diff --git a/subscription/pom.xml b/subscription/pom.xml
index 53ae54d..a2d2459 100644
--- a/subscription/pom.xml
+++ b/subscription/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-subscription</artifactId>
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
index e6bdb7b..9794ac6 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
@@ -148,7 +148,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
}
private List<SubscriptionSpecifier> verifyAndBuildSubscriptionSpecifiers(final SubscriptionBaseBundle bundle,
- @Nullable final EntitlementSpecifier baseOrStandalonePlanSpecifier,
+ @Nullable final EntitlementSpecifier baseOrFirstStandalonePlanSpecifier,
final Iterable<EntitlementSpecifier> entitlements,
final boolean isMigrated,
final InternalCallContext context,
@@ -188,7 +188,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
}
final DateTime bundleStartDate;
- if (baseOrStandalonePlanSpecifier != null) {
+ if (baseOrFirstStandalonePlanSpecifier != null) {
bundleStartDate = effectiveDate;
} else {
final SubscriptionBase baseSubscription = dao.getBaseSubscription(bundle.getId(), catalog, context);
@@ -219,16 +219,18 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
final SubscriptionBaseWithAddOnsSpecifier subscriptionBaseWithAddOnsSpecifier,
final DateTime effectiveDate,
final Collection<EntitlementSpecifier> outputEntitlementSpecifier) throws SubscriptionBaseApiException {
- EntitlementSpecifier baseOrStandalonePlanSpecifier = null;
+ EntitlementSpecifier basePlanSpecifier = null;
final Collection<EntitlementSpecifier> addOnSpecifiers = new ArrayList<EntitlementSpecifier>();
+ final List<EntitlementSpecifier> standaloneSpecifiers = new ArrayList<EntitlementSpecifier>();
try {
for (final EntitlementSpecifier cur : subscriptionBaseWithAddOnsSpecifier.getEntitlementSpecifiers()) {
final boolean isBase = isBaseSpecifier(catalog, effectiveDate, cur);
final boolean isStandalone = isStandaloneSpecifier(catalog, effectiveDate, cur);
- final boolean isBaseOrStandaloneSpecifier = isBase || isStandalone;
- if (isBaseOrStandaloneSpecifier) {
- if (baseOrStandalonePlanSpecifier == null) {
- baseOrStandalonePlanSpecifier = cur;
+ if (isStandalone) {
+ standaloneSpecifiers.add(cur);
+ } else if (isBase) {
+ if (basePlanSpecifier == null) {
+ basePlanSpecifier = cur;
} else {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_INVALID_ENTITLEMENT_SPECIFIER);
}
@@ -240,11 +242,21 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
throw new SubscriptionBaseApiException(e);
}
- if (baseOrStandalonePlanSpecifier != null) {
- outputEntitlementSpecifier.add(baseOrStandalonePlanSpecifier);
+ if (basePlanSpecifier != null) {
+ outputEntitlementSpecifier.add(basePlanSpecifier);
}
outputEntitlementSpecifier.addAll(addOnSpecifiers);
- return baseOrStandalonePlanSpecifier;
+
+ if (!outputEntitlementSpecifier.isEmpty() && !standaloneSpecifiers.isEmpty()) {
+ throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_INVALID_ENTITLEMENT_SPECIFIER);
+ }
+
+ if (standaloneSpecifiers.isEmpty()) {
+ return basePlanSpecifier;
+ } else {
+ outputEntitlementSpecifier.addAll(standaloneSpecifiers);
+ return standaloneSpecifiers.get(0);
+ }
}
private boolean isBaseSpecifier(final Catalog catalog, final DateTime effectiveDate, final EntitlementSpecifier cur) throws CatalogApiException {
@@ -271,7 +283,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
final Collection<EntitlementSpecifier> reorderedSpecifiers = new ArrayList<EntitlementSpecifier>();
// Note: billingRequestedDateRaw might not be accurate here (add-on with a too early date passed)?
- final EntitlementSpecifier baseOrStandalonePlanSpecifier = sanityAndReorderBPOrStandaloneSpecFirst(catalog, subscriptionBaseWithAddOnsSpecifier, billingRequestedDateRaw, reorderedSpecifiers);
+ final EntitlementSpecifier baseOrFirstStandalonePlanSpecifier = sanityAndReorderBPOrStandaloneSpecFirst(catalog, subscriptionBaseWithAddOnsSpecifier, billingRequestedDateRaw, reorderedSpecifiers);
DateTime billingRequestedDate = billingRequestedDateRaw;
SubscriptionBaseBundle bundle = null;
@@ -282,7 +294,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_INVALID_ENTITLEMENT_SPECIFIER);
}
} else if (subscriptionBaseWithAddOnsSpecifier.getBundleExternalKey() != null &&
- baseOrStandalonePlanSpecifier == null) { // Skip the expensive checks if we are about to create the bundle (validation will be done in SubscriptionDao#createSubscriptionBundle)
+ baseOrFirstStandalonePlanSpecifier == null) { // Skip the expensive checks if we are about to create the bundle (validation will be done in SubscriptionDao#createSubscriptionBundle)
final List<SubscriptionBaseBundle> existingBundles = dao.getSubscriptionBundlesForKey(subscriptionBaseWithAddOnsSpecifier.getBundleExternalKey(), context);
final SubscriptionBaseBundle tmp = getActiveBundleForKeyNotException(existingBundles, dao, clock, catalog, context);
if (tmp == null) {
@@ -303,12 +315,12 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
}
}
- if (bundle == null && baseOrStandalonePlanSpecifier != null) {
+ if (bundle == null && baseOrFirstStandalonePlanSpecifier != null) {
bundle = createBundleForAccount(accountId,
subscriptionBaseWithAddOnsSpecifier.getBundleExternalKey(),
renameCancelledBundleIfExist,
context);
- } else if (bundle != null && baseSubscription != null && baseOrStandalonePlanSpecifier != null && isBaseSpecifier(catalog, billingRequestedDateRaw, baseOrStandalonePlanSpecifier)) {
+ } else if (bundle != null && baseSubscription != null && baseOrFirstStandalonePlanSpecifier != null && isBaseSpecifier(catalog, billingRequestedDateRaw, baseOrFirstStandalonePlanSpecifier)) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_BP_EXISTS, bundle.getExternalKey());
} else if (bundle == null) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_INVALID_ENTITLEMENT_SPECIFIER);
@@ -317,7 +329,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
final SubscriptionAndAddOnsSpecifier subscriptionAndAddOnsSpecifier = new SubscriptionAndAddOnsSpecifier(bundle,
billingRequestedDate,
verifyAndBuildSubscriptionSpecifiers(bundle,
- baseOrStandalonePlanSpecifier,
+ baseOrFirstStandalonePlanSpecifier,
reorderedSpecifiers,
subscriptionBaseWithAddOnsSpecifier.isMigrated(),
context,
@@ -850,14 +862,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
private CacheLoaderArgument createBundleIdFromSubscriptionIdCacheLoaderArgument(final InternalTenantContext internalTenantContext) {
final BundleIdFromSubscriptionIdCacheLoader.LoaderCallback loaderCallback = new BundleIdFromSubscriptionIdCacheLoader.LoaderCallback() {
public UUID loadBundleId(final UUID subscriptionId, final InternalTenantContext internalTenantContext) {
- final SubscriptionBase subscriptionBase;
- try {
- subscriptionBase = getSubscriptionFromId(subscriptionId, internalTenantContext);
- } catch (final SubscriptionBaseApiException e) {
- log.warn("Unable to retrieve subscription for id='{}'", subscriptionId);
- return null;
- }
- return subscriptionBase.getBundleId();
+ return dao.getBundleIdFromSubscriptionId(subscriptionId, internalTenantContext);
}
};
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java b/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java
index 27b31f3..29cedce 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java
@@ -144,10 +144,15 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
try {
final DefaultSubscriptionBase subscriptionBase = new DefaultSubscriptionBase(subscription.getBuilder(), this, clock);
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscriptionBase.getBundleId(), context);
- final List<SubscriptionBaseEvent> events = getEventsOnCreation(subscriptionBase.getId(), subscriptionBase.getAlignStartDate(),
- subscriptionBase.getBundleStartDate(), subscription.getPlan(),
- subscription.getInitialPhase(), subscription.getRealPriceList(),
- subscription.getEffectiveDate(), fullCatalog, internalCallContext);
+ final List<SubscriptionBaseEvent> events = getEventsOnCreation(subscriptionBase.getId(),
+ subscriptionBase.getAlignStartDate(),
+ subscriptionBase.getBundleStartDate(),
+ subscription.getPlan(),
+ subscription.getInitialPhase(),
+ subscription.getRealPriceList(),
+ subscription.getEffectiveDate(),
+ fullCatalog,
+ internalCallContext);
eventsMap.put(subscriptionBase.getId(), events);
subscriptionBaseList.add(subscriptionBase);
} catch (final CatalogApiException e) {
@@ -434,13 +439,23 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
}
@Override
- public List<SubscriptionBaseEvent> getEventsOnCreation(final UUID subscriptionId, final DateTime alignStartDate, final DateTime bundleStartDate,
- final Plan plan, final PhaseType initialPhase,
- final String realPriceList, final DateTime effectiveDate,
+ public List<SubscriptionBaseEvent> getEventsOnCreation(final UUID subscriptionId,
+ final DateTime alignStartDate,
+ final DateTime bundleStartDate,
+ final Plan plan,
+ final PhaseType initialPhase,
+ final String realPriceList,
+ final DateTime effectiveDate,
final Catalog fullCatalog,
final InternalTenantContext internalTenantContext) throws CatalogApiException, SubscriptionBaseApiException {
- final TimedPhase[] curAndNextPhases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, initialPhase,
- realPriceList, effectiveDate, fullCatalog, internalTenantContext);
+ final TimedPhase[] curAndNextPhases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate,
+ bundleStartDate,
+ plan,
+ initialPhase,
+ realPriceList,
+ effectiveDate,
+ fullCatalog,
+ internalTenantContext);
final ApiEventBuilder createBuilder = new ApiEventBuilder()
.setSubscriptionId(subscriptionId)
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
index 1c11dae..065e0c8 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
@@ -301,6 +301,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
final SubscriptionBaseBundle unusedBundle = findExistingUnusedBundleForExternalKeyAndAccount(existingBundles, entitySqlDaoWrapperFactory);
if (unusedBundle != null) {
+ log.info("Found unused bundle for externalKey='{}': bundleId='{}'", bundle.getExternalKey(), unusedBundle.getId());
return unusedBundle;
}
final BundleSqlDao bundleSqlDao = entitySqlDaoWrapperFactory.become(BundleSqlDao.class);
@@ -319,6 +320,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
if (s.getState() != EntitlementState.CANCELLED) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_ACTIVE_BUNDLE_KEY_EXISTS, bundle.getExternalKey());
} else if (renameCancelledBundleIfExist) {
+ log.info("Renaming bundles with externalKey='{}', prefix='cncl'", bundle.getExternalKey());
// Note that if bundle belongs to a different account, context is not the context for this target account,
// but the underlying sql operation does not use the account info
bundleSqlDao.renameBundleExternalKey(bundle.getExternalKey(), "cncl", context);
@@ -361,6 +363,17 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
@Override
+ public UUID getBundleIdFromSubscriptionId(final UUID subscriptionId, final InternalTenantContext context) {
+ return transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<UUID>() {
+ @Override
+ public UUID inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
+ final SubscriptionModelDao subscriptionModel = entitySqlDaoWrapperFactory.become(SubscriptionSqlDao.class).getById(subscriptionId.toString(), context);
+ return subscriptionModel.getBundleId();
+ }
+ });
+ }
+
+ @Override
public List<SubscriptionBase> getSubscriptions(final UUID bundleId, final List<SubscriptionBaseEvent> dryRunEvents, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
return buildBundleSubscriptions(getSubscriptionFromBundleId(bundleId, context), null, dryRunEvents, catalog, context);
}
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java
index 3e6dd6c..242676b 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java
@@ -59,6 +59,8 @@ public interface SubscriptionDao extends EntityDao<SubscriptionBundleModelDao, S
public SubscriptionBase getSubscriptionFromId(UUID subscriptionId, final Catalog catalog, InternalTenantContext context) throws CatalogApiException;
+ public UUID getBundleIdFromSubscriptionId(UUID subscriptionId, InternalTenantContext context);
+
// SubscriptionBase retrieval
public SubscriptionBase getBaseSubscription(UUID bundleId, final Catalog catalog, InternalTenantContext context) throws CatalogApiException;
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java b/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
index 19dbef1..8b5a74e 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
@@ -198,6 +198,11 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
}
@Override
+ public UUID getBundleIdFromSubscriptionId(final UUID subscriptionId, final InternalTenantContext context) {
+ return getSubscriptionFromId(subscriptionId, null, context).getBundleId();
+ }
+
+ @Override
public List<SubscriptionBaseEvent> createSubscriptionsWithAddOns(final List<SubscriptionBaseWithAddOns> subscriptions,
final Map<UUID, List<SubscriptionBaseEvent>> initialEventsMap,
final Catalog catalog,
tenant/pom.xml 2(+1 -1)
diff --git a/tenant/pom.xml b/tenant/pom.xml
index c83a4c3..3936329 100644
--- a/tenant/pom.xml
+++ b/tenant/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-tenant</artifactId>
usage/pom.xml 2(+1 -1)
diff --git a/usage/pom.xml b/usage/pom.xml
index c648b85..2858c6c 100644
--- a/usage/pom.xml
+++ b/usage/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-usage</artifactId>
util/pom.xml 2(+1 -1)
diff --git a/util/pom.xml b/util/pom.xml
index fe72a83..946d4c3 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -21,7 +21,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.19.10-SNAPSHOT</version>
+ <version>0.19.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-util</artifactId>