diff --git a/java/google/registry/flows/domain/DomainFlowUtils.java b/java/google/registry/flows/domain/DomainFlowUtils.java index b199f9582..d6fbd0f98 100644 --- a/java/google/registry/flows/domain/DomainFlowUtils.java +++ b/java/google/registry/flows/domain/DomainFlowUtils.java @@ -36,6 +36,7 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.isAtOrAfter; import static google.registry.util.DateTimeUtils.leapSafeAddYears; import static google.registry.util.DomainNameUtils.ACE_PREFIX; +import static google.registry.util.FormattingLogger.getLoggerForCallerClass; import com.google.common.base.CharMatcher; import com.google.common.base.Joiner; @@ -63,6 +64,7 @@ import google.registry.model.EppResource; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent.Flag; import google.registry.model.billing.BillingEvent.Reason; +import google.registry.model.billing.BillingEvent.Recurring; import google.registry.model.contact.ContactResource; import google.registry.model.domain.DesignatedContact; import google.registry.model.domain.DesignatedContact.Type; @@ -104,6 +106,7 @@ import google.registry.model.registry.label.ReservationType; import google.registry.model.registry.label.ReservedList; import google.registry.model.reporting.HistoryEntry; import google.registry.model.tmch.ClaimsListShard; +import google.registry.util.FormattingLogger; import google.registry.util.Idn; import java.math.BigDecimal; import java.util.HashSet; @@ -118,6 +121,8 @@ import org.joda.time.DateTime; /** Static utility functions for domain flows. */ public class DomainFlowUtils { + private static final FormattingLogger logger = getLoggerForCallerClass(); + /** Map from launch phases to the equivalent tld states. */ private static final ImmutableMap LAUNCH_PHASE_TO_TLD_STATE = ImmutableMap.of( @@ -506,9 +511,17 @@ public class DomainFlowUtils { ofy().save().entity(updatedAutorenewPollMessage); } - ofy().save().entity(ofy().load().key(domain.getAutorenewBillingEvent()).now().asBuilder() - .setRecurrenceEndTime(newEndTime) - .build()); + Recurring recurring = ofy().load().key(domain.getAutorenewBillingEvent()).now(); + // TODO(b/27472322): Revert handling of recurring being null once bad data is cleaned from prod. + // It shouldn't ever actually be null, and we only have some null data left because of issues + // dating back to the Registry 2.0 migration. + if (recurring == null) { + logger.warningfmt( + "Domain name %s has null autorenew billing event; ignoring. Domain key: %s.", + domain.getFullyQualifiedDomainName(), Key.create(domain)); + } else { + ofy().save().entity(recurring.asBuilder().setRecurrenceEndTime(newEndTime).build()); + } } /** diff --git a/javatests/google/registry/flows/domain/DomainDeleteFlowTest.java b/javatests/google/registry/flows/domain/DomainDeleteFlowTest.java index 0eaabfb06..ccbaf134d 100644 --- a/javatests/google/registry/flows/domain/DomainDeleteFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainDeleteFlowTest.java @@ -492,6 +492,20 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase