diff --git a/core/src/main/java/google/registry/flows/FlowModule.java b/core/src/main/java/google/registry/flows/FlowModule.java index 0659a756f..8683ed8ae 100644 --- a/core/src/main/java/google/registry/flows/FlowModule.java +++ b/core/src/main/java/google/registry/flows/FlowModule.java @@ -20,6 +20,7 @@ import com.google.common.base.Strings; import dagger.Module; import dagger.Provides; import google.registry.flows.picker.FlowPicker; +import google.registry.model.domain.DomainHistory; import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppcommon.Trid; @@ -239,6 +240,12 @@ public class FlowModule { return historyBuilder; } + @Provides + static DomainHistory.Builder provideDomainHistoryBuilder( + HistoryEntry.Builder historyEntryBuilder) { + return new DomainHistory.Builder().copyFrom(historyEntryBuilder.build()); + } + /** * Provides a partially filled in {@link EppResponse} builder. * diff --git a/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java b/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java index b514c2e57..1a155ec98 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java @@ -80,6 +80,7 @@ import google.registry.model.billing.BillingEvent.Recurring; import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainCommand; import google.registry.model.domain.DomainCommand.Create; +import google.registry.model.domain.DomainHistory; import google.registry.model.domain.GracePeriod; import google.registry.model.domain.Period; import google.registry.model.domain.fee.FeeCreateCommandExtension; @@ -206,7 +207,7 @@ public class DomainCreateFlow implements TransactionalFlow { @Inject @ClientId String clientId; @Inject @TargetId String targetId; @Inject @Superuser boolean isSuperuser; - @Inject HistoryEntry.Builder historyBuilder; + @Inject DomainHistory.Builder historyBuilder; @Inject EppResponse.Builder responseBuilder; @Inject AllocationTokenFlowUtils allocationTokenFlowUtils; @Inject DomainCreateFlowCustomLogic flowCustomLogic; @@ -303,8 +304,8 @@ public class DomainCreateFlow implements TransactionalFlow { validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class)); String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr()); DateTime registrationExpirationTime = leapSafeAddYears(now, years); - HistoryEntry historyEntry = buildHistoryEntry( - repoId, registry, now, period, registry.getAddGracePeriodLength()); + DomainHistory domainHistory = + buildHistoryEntry(repoId, registry, now, period, registry.getAddGracePeriodLength()); // Bill for the create. BillingEvent.OneTime createBillingEvent = createOneTimeBillingEvent( @@ -314,20 +315,16 @@ public class DomainCreateFlow implements TransactionalFlow { isReserved(domainName, isSunriseCreate), years, feesAndCredits, - historyEntry, + domainHistory, allocationToken, now); // Create a new autorenew billing event and poll message starting at the expiration time. BillingEvent.Recurring autorenewBillingEvent = - createAutorenewBillingEvent(historyEntry, registrationExpirationTime); + createAutorenewBillingEvent(domainHistory, registrationExpirationTime); PollMessage.Autorenew autorenewPollMessage = - createAutorenewPollMessage(historyEntry, registrationExpirationTime); + createAutorenewPollMessage(domainHistory, registrationExpirationTime); ImmutableSet.Builder entitiesToSave = new ImmutableSet.Builder<>(); - entitiesToSave.add( - historyEntry, - createBillingEvent, - autorenewBillingEvent, - autorenewPollMessage); + entitiesToSave.add(createBillingEvent, autorenewBillingEvent, autorenewPollMessage); // Bill for EAP cost, if any. if (!feesAndCredits.getEapCost().isZero()) { entitiesToSave.add(createEapBillingEvent(feesAndCredits, createBillingEvent)); @@ -337,7 +334,7 @@ public class DomainCreateFlow implements TransactionalFlow { if (getReservationTypes(domainName).contains(NAME_COLLISION)) { statuses.add(SERVER_HOLD); entitiesToSave.add( - createNameCollisionOneTimePollMessage(targetId, historyEntry, clientId, now)); + createNameCollisionOneTimePollMessage(targetId, domainHistory, clientId, now)); } DomainBase newDomain = @@ -365,13 +362,13 @@ public class DomainCreateFlow implements TransactionalFlow { .build(); entitiesToSave.add( newDomain, + domainHistory.asBuilder().setDomainContent(newDomain).build(), ForeignKeyIndex.create(newDomain, newDomain.getDeletionTime()), EppResourceIndex.create(Key.create(newDomain))); if (allocationToken.isPresent() && TokenType.SINGLE_USE.equals(allocationToken.get().getTokenType())) { entitiesToSave.add( - allocationTokenFlowUtils.redeemToken( - allocationToken.get(), HistoryEntry.createVKey(Key.create(historyEntry)))); + allocationTokenFlowUtils.redeemToken(allocationToken.get(), domainHistory.createVKey())); } enqueueTasks(newDomain, hasSignedMarks, hasClaimsNotice); @@ -379,7 +376,7 @@ public class DomainCreateFlow implements TransactionalFlow { flowCustomLogic.beforeSave( DomainCreateFlowCustomLogic.BeforeSaveParameters.newBuilder() .setNewDomain(newDomain) - .setHistoryEntry(historyEntry) + .setHistoryEntry(domainHistory) .setEntityChanges( EntityChanges.newBuilder().setSaves(entitiesToSave.build()).build()) .setYears(years) @@ -483,7 +480,7 @@ public class DomainCreateFlow implements TransactionalFlow { : null); } - private HistoryEntry buildHistoryEntry( + private DomainHistory buildHistoryEntry( String repoId, Registry registry, DateTime now, Period period, Duration addGracePeriod) { // We ignore prober transactions if (registry.getTldType() == TldType.REAL) { @@ -511,7 +508,7 @@ public class DomainCreateFlow implements TransactionalFlow { boolean isReserved, int years, FeesAndCredits feesAndCredits, - HistoryEntry historyEntry, + DomainHistory domainHistory, Optional allocationToken, DateTime now) { ImmutableSet.Builder flagsBuilder = new ImmutableSet.Builder<>(); @@ -540,12 +537,12 @@ public class DomainCreateFlow implements TransactionalFlow { ? registry.getAnchorTenantAddGracePeriodLength() : registry.getAddGracePeriodLength())) .setFlags(flagsBuilder.build()) - .setParent(historyEntry) + .setParent(domainHistory) .build(); } private Recurring createAutorenewBillingEvent( - HistoryEntry historyEntry, DateTime registrationExpirationTime) { + DomainHistory domainHistory, DateTime registrationExpirationTime) { return new BillingEvent.Recurring.Builder() .setReason(Reason.RENEW) .setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) @@ -553,7 +550,7 @@ public class DomainCreateFlow implements TransactionalFlow { .setClientId(clientId) .setEventTime(registrationExpirationTime) .setRecurrenceEndTime(END_OF_TIME) - .setParent(historyEntry) + .setParent(domainHistory) .build(); } diff --git a/core/src/main/java/google/registry/model/contact/ContactHistory.java b/core/src/main/java/google/registry/model/contact/ContactHistory.java index feb695227..c93d63991 100644 --- a/core/src/main/java/google/registry/model/contact/ContactHistory.java +++ b/core/src/main/java/google/registry/model/contact/ContactHistory.java @@ -56,6 +56,7 @@ import javax.persistence.PostLoad; public class ContactHistory extends HistoryEntry implements SqlEntity { // Store ContactBase instead of ContactResource so we don't pick up its @Id + // Nullable for the sake of pre-Registry-3.0 history objects @Nullable ContactBase contactBase; @Id @@ -193,9 +194,13 @@ public class ContactHistory extends HistoryEntry implements SqlEntity { super(instance); } - public Builder setContactBase(ContactBase contactBase) { + public Builder setContactBase(@Nullable ContactBase contactBase) { + // Nullable for the sake of pre-Registry-3.0 history objects + if (contactBase == null) { + return this; + } getInstance().contactBase = contactBase; - return this; + return super.setParent(contactBase); } public Builder setContactRepoId(String contactRepoId) { diff --git a/core/src/main/java/google/registry/model/domain/DomainHistory.java b/core/src/main/java/google/registry/model/domain/DomainHistory.java index 3051f20e5..eede8710d 100644 --- a/core/src/main/java/google/registry/model/domain/DomainHistory.java +++ b/core/src/main/java/google/registry/model/domain/DomainHistory.java @@ -33,6 +33,7 @@ import google.registry.persistence.VKey; import google.registry.schema.replay.DatastoreEntity; import google.registry.schema.replay.SqlEntity; import java.io.Serializable; +import java.util.HashSet; import java.util.Optional; import java.util.Set; import javax.annotation.Nullable; @@ -76,6 +77,7 @@ import javax.persistence.Table; public class DomainHistory extends HistoryEntry implements SqlEntity { // Store DomainContent instead of DomainBase so we don't pick up its @Id + // Nullable for the sake of pre-Registry-3.0 history objects @Nullable DomainContent domainContent; @Id @@ -126,7 +128,8 @@ public class DomainHistory extends HistoryEntry implements SqlEntity { insertable = false, updatable = false) }) - Set dsDataHistories = ImmutableSet.of(); + // HashSet rather than ImmutableSet so that Hibernate can fill them out lazily on request + Set dsDataHistories = new HashSet<>(); @Ignore @OneToMany( @@ -145,7 +148,8 @@ public class DomainHistory extends HistoryEntry implements SqlEntity { insertable = false, updatable = false) }) - Set gracePeriodHistories = ImmutableSet.of(); + // HashSet rather than ImmutableSet so that Hibernate can fill them out lazily on request + Set gracePeriodHistories = new HashSet<>(); @Override @Nullable @@ -341,9 +345,13 @@ public class DomainHistory extends HistoryEntry implements SqlEntity { super(instance); } - public Builder setDomainContent(DomainContent domainContent) { + public Builder setDomainContent(@Nullable DomainContent domainContent) { + // Nullable for the sake of pre-Registry-3.0 history objects + if (domainContent == null) { + return this; + } getInstance().domainContent = domainContent; - return this; + return super.setParent(domainContent); } public Builder setDomainRepoId(String domainRepoId) { diff --git a/core/src/main/java/google/registry/model/domain/GracePeriodBase.java b/core/src/main/java/google/registry/model/domain/GracePeriodBase.java index 1d1cc2217..9dc547a56 100644 --- a/core/src/main/java/google/registry/model/domain/GracePeriodBase.java +++ b/core/src/main/java/google/registry/model/domain/GracePeriodBase.java @@ -38,7 +38,7 @@ import org.joda.time.DateTime; public class GracePeriodBase extends ImmutableObject { /** Unique id required for hibernate representation. */ - @Transient Long gracePeriodId; + @Transient long gracePeriodId; /** Repository id for the domain which this grace period belongs to. */ @Ignore diff --git a/core/src/main/java/google/registry/model/host/HostHistory.java b/core/src/main/java/google/registry/model/host/HostHistory.java index 2f91349f9..c3821f656 100644 --- a/core/src/main/java/google/registry/model/host/HostHistory.java +++ b/core/src/main/java/google/registry/model/host/HostHistory.java @@ -57,6 +57,7 @@ import javax.persistence.PostLoad; public class HostHistory extends HistoryEntry implements SqlEntity { // Store HostBase instead of HostResource so we don't pick up its @Id + // Nullable for the sake of pre-Registry-3.0 history objects @Nullable HostBase hostBase; @Id @@ -194,9 +195,13 @@ public class HostHistory extends HistoryEntry implements SqlEntity { super(instance); } - public Builder setHostBase(HostBase hostBase) { + public Builder setHostBase(@Nullable HostBase hostBase) { + // Nullable for the sake of pre-Registry-3.0 history objects + if (hostBase == null) { + return this; + } getInstance().hostBase = hostBase; - return this; + return super.setParent(hostBase); } public Builder setHostRepoId(String hostRepoId) { diff --git a/core/src/main/java/google/registry/model/ofy/DatastoreTransactionManager.java b/core/src/main/java/google/registry/model/ofy/DatastoreTransactionManager.java index dbea67f74..38d3a6591 100644 --- a/core/src/main/java/google/registry/model/ofy/DatastoreTransactionManager.java +++ b/core/src/main/java/google/registry/model/ofy/DatastoreTransactionManager.java @@ -39,6 +39,8 @@ import google.registry.model.reporting.HistoryEntry; import google.registry.persistence.VKey; import google.registry.persistence.transaction.QueryComposer; import google.registry.persistence.transaction.TransactionManager; +import google.registry.schema.replay.DatastoreEntity; +import google.registry.schema.replay.SqlEntity; import java.util.List; import java.util.NoSuchElementException; import java.util.Optional; @@ -141,22 +143,23 @@ public class DatastoreTransactionManager implements TransactionManager { @Override public void putAll(Object... entities) { - syncIfTransactionless(getOfy().save().entities(entities)); + syncIfTransactionless( + getOfy().save().entities(toDatastoreEntities(ImmutableList.copyOf(entities)))); } @Override public void putAll(ImmutableCollection entities) { - syncIfTransactionless(getOfy().save().entities(entities)); + syncIfTransactionless(getOfy().save().entities(toDatastoreEntities(entities))); } @Override public void putWithoutBackup(Object entity) { - syncIfTransactionless(getOfy().saveWithoutBackup().entities(entity)); + syncIfTransactionless(getOfy().saveWithoutBackup().entities(toDatastoreEntity(entity))); } @Override public void putAllWithoutBackup(ImmutableCollection entities) { - syncIfTransactionless(getOfy().saveWithoutBackup().entities(entities)); + syncIfTransactionless(getOfy().saveWithoutBackup().entities(toDatastoreEntities(entities))); } @Override @@ -181,7 +184,7 @@ public class DatastoreTransactionManager implements TransactionManager { @Override public boolean exists(Object entity) { - return getOfy().load().key(Key.create(entity)).now() != null; + return getOfy().load().key(Key.create(toDatastoreEntity(entity))).now() != null; } @Override @@ -210,8 +213,7 @@ public class DatastoreTransactionManager implements TransactionManager { return getOfy().load().keys(keyMap.keySet()).entrySet().stream() .collect( toImmutableMap( - entry -> keyMap.get(entry.getKey()), - entry -> toChildHistoryEntryIfPossible(entry.getValue()))); + entry -> keyMap.get(entry.getKey()), entry -> toSqlEntity(entry.getValue()))); } @Override @@ -244,7 +246,7 @@ public class DatastoreTransactionManager implements TransactionManager { @Override public T loadByEntity(T entity) { - return ofy().load().entity(entity).now(); + return (T) toSqlEntity(ofy().load().entity(toDatastoreEntity(entity)).now()); } @Override @@ -286,7 +288,7 @@ public class DatastoreTransactionManager implements TransactionManager { @Override public void delete(Object entity) { - syncIfTransactionless(getOfy().delete().entity(entity)); + syncIfTransactionless(getOfy().delete().entity(toDatastoreEntity(entity))); } @Override @@ -304,7 +306,7 @@ public class DatastoreTransactionManager implements TransactionManager { @Override public void deleteWithoutBackup(Object entity) { - syncIfTransactionless(getOfy().deleteWithoutBackup().entity(entity)); + syncIfTransactionless(getOfy().deleteWithoutBackup().entity(toDatastoreEntity(entity))); } @Override @@ -348,28 +350,52 @@ public class DatastoreTransactionManager implements TransactionManager { */ private void saveEntity(Object entity) { checkArgumentNotNull(entity, "entity must be specified"); - if (entity instanceof HistoryEntry) { - entity = ((HistoryEntry) entity).asHistoryEntry(); - } - syncIfTransactionless(getOfy().save().entity(entity)); + syncIfTransactionless(getOfy().save().entity(toDatastoreEntity(entity))); } @Nullable private T loadNullable(VKey key) { - return toChildHistoryEntryIfPossible(getOfy().load().key(key.getOfyKey()).now()); + return toSqlEntity(getOfy().load().key(key.getOfyKey()).now()); } - /** Converts a nonnull {@link HistoryEntry} to the child format, e.g. {@link DomainHistory} */ + /** + * Converts a possible {@link SqlEntity} to a {@link DatastoreEntity}. + * + *

One example is that this would convert a {@link DomainHistory} to a {@link HistoryEntry}. + */ + private static Object toDatastoreEntity(@Nullable Object obj) { + if (obj instanceof SqlEntity) { + Optional possibleDatastoreEntity = ((SqlEntity) obj).toDatastoreEntity(); + if (possibleDatastoreEntity.isPresent()) { + return possibleDatastoreEntity.get(); + } + } + return obj; + } + + /** Converts many possible {@link SqlEntity} objects to {@link DatastoreEntity} objects. */ + private static ImmutableList toDatastoreEntities(ImmutableCollection collection) { + return collection.stream() + .map(DatastoreTransactionManager::toDatastoreEntity) + .collect(toImmutableList()); + } + + /** + * Converts an object to the corresponding {@link SqlEntity} if necessary and possible. + * + *

This should be used when returning objects from Datastore to make sure they reflect the most + * recent type of the object in question. + */ @SuppressWarnings("unchecked") - public static T toChildHistoryEntryIfPossible(@Nullable T obj) { + public static T toSqlEntity(@Nullable T obj) { // NB: The Key of the object in question may not necessarily be the resulting class that we - // wish to have. Because all *History classes are @EntitySubclasses, their Keys will have type - // HistoryEntry -- even if you create them based off the *History class. - if (obj instanceof HistoryEntry - && !(obj instanceof ContactHistory) - && !(obj instanceof DomainHistory) - && !(obj instanceof HostHistory)) { - return (T) ((HistoryEntry) obj).toChildHistoryEntity(); + // wish to have. For example, because all *History classes are @EntitySubclasses, their Keys + // will have type HistoryEntry -- even if you create them based off the *History class. + if (obj instanceof DatastoreEntity && !(obj instanceof SqlEntity)) { + Optional possibleSqlEntity = ((DatastoreEntity) obj).toSqlEntity(); + if (possibleSqlEntity.isPresent()) { + return (T) possibleSqlEntity.get(); + } } return obj; } diff --git a/core/src/main/java/google/registry/model/reporting/HistoryEntryDao.java b/core/src/main/java/google/registry/model/reporting/HistoryEntryDao.java index c86b4b103..3319ef6cb 100644 --- a/core/src/main/java/google/registry/model/reporting/HistoryEntryDao.java +++ b/core/src/main/java/google/registry/model/reporting/HistoryEntryDao.java @@ -51,12 +51,15 @@ public class HistoryEntryDao { public static Iterable loadAllHistoryObjects( DateTime afterTime, DateTime beforeTime) { if (tm().isOfy()) { - return ofy() - .load() - .type(HistoryEntry.class) - .order("modificationTime") - .filter("modificationTime >=", afterTime) - .filter("modificationTime <=", beforeTime); + return Streams.stream( + ofy() + .load() + .type(HistoryEntry.class) + .order("modificationTime") + .filter("modificationTime >=", afterTime) + .filter("modificationTime <=", beforeTime)) + .map(HistoryEntry::toChildHistoryEntity) + .collect(toImmutableList()); } else { return jpaTm() .transact( @@ -78,13 +81,16 @@ public class HistoryEntryDao { public static Iterable loadHistoryObjectsForResource( VKey parentKey, DateTime afterTime, DateTime beforeTime) { if (tm().isOfy()) { - return ofy() - .load() - .type(HistoryEntry.class) - .ancestor(parentKey.getOfyKey()) - .order("modificationTime") - .filter("modificationTime >=", afterTime) - .filter("modificationTime <=", beforeTime); + return Streams.stream( + ofy() + .load() + .type(HistoryEntry.class) + .ancestor(parentKey.getOfyKey()) + .order("modificationTime") + .filter("modificationTime >=", afterTime) + .filter("modificationTime <=", beforeTime)) + .map(HistoryEntry::toChildHistoryEntity) + .collect(toImmutableList()); } else { return jpaTm() .transact(() -> loadHistoryObjectsForResourceFromSql(parentKey, afterTime, beforeTime)); diff --git a/core/src/main/java/google/registry/persistence/transaction/JpaTransactionManagerImpl.java b/core/src/main/java/google/registry/persistence/transaction/JpaTransactionManagerImpl.java index d75b80804..9381f2c31 100644 --- a/core/src/main/java/google/registry/persistence/transaction/JpaTransactionManagerImpl.java +++ b/core/src/main/java/google/registry/persistence/transaction/JpaTransactionManagerImpl.java @@ -18,7 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.collect.ImmutableSet.toImmutableSet; -import static google.registry.model.ofy.DatastoreTransactionManager.toChildHistoryEntryIfPossible; +import static google.registry.model.ofy.DatastoreTransactionManager.toSqlEntity; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import static java.util.AbstractMap.SimpleEntry; import static java.util.stream.Collectors.joining; @@ -268,7 +268,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager { } assertInTransaction(); // Necessary due to the changes in HistoryEntry representation during the migration to SQL - Object toPersist = toChildHistoryEntryIfPossible(entity); + Object toPersist = toSqlEntity(entity); getEntityManager().persist(toPersist); transactionInfo.get().addUpdate(toPersist); } @@ -298,7 +298,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager { } assertInTransaction(); // Necessary due to the changes in HistoryEntry representation during the migration to SQL - Object toPersist = toChildHistoryEntryIfPossible(entity); + Object toPersist = toSqlEntity(entity); getEntityManager().merge(toPersist); transactionInfo.get().addUpdate(toPersist); } @@ -338,7 +338,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager { assertInTransaction(); checkArgument(exists(entity), "Given entity does not exist"); // Necessary due to the changes in HistoryEntry representation during the migration to SQL - Object toPersist = toChildHistoryEntryIfPossible(entity); + Object toPersist = toSqlEntity(entity); getEntityManager().merge(toPersist); transactionInfo.get().addUpdate(toPersist); } @@ -371,7 +371,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager { @Override public boolean exists(Object entity) { checkArgumentNotNull(entity, "entity must be specified"); - entity = toChildHistoryEntryIfPossible(entity); + entity = toSqlEntity(entity); EntityType entityType = getEntityType(entity.getClass()); ImmutableSet entityIds = getEntityIdsFromEntity(entityType, entity); return exists(entityType.getName(), entityIds); @@ -414,7 +414,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager { @Override public ImmutableList loadByEntitiesIfPresent(Iterable entities) { return Streams.stream(entities) - .map(DatastoreTransactionManager::toChildHistoryEntryIfPossible) + .map(DatastoreTransactionManager::toSqlEntity) .filter(this::exists) .map(this::loadByEntity) .collect(toImmutableList()); @@ -449,9 +449,8 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager { public T loadByEntity(T entity) { checkArgumentNotNull(entity, "entity must be specified"); assertInTransaction(); - entity = toChildHistoryEntryIfPossible(entity); // If the caller requested a HistoryEntry, load the corresponding *History class - T possibleChild = toChildHistoryEntryIfPossible(entity); + T possibleChild = toSqlEntity(entity); return (T) loadByKey( VKey.createSql( @@ -511,7 +510,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager { return; } assertInTransaction(); - entity = toChildHistoryEntryIfPossible(entity); + entity = toSqlEntity(entity); Object managedEntity = entity; if (!getEntityManager().contains(entity)) { managedEntity = getEntityManager().merge(entity); diff --git a/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java b/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java index ef51fc339..e6f92819e 100644 --- a/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java +++ b/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java @@ -751,11 +751,11 @@ class EppLifecycleDomainTest extends EppTestCase { .hasResponse( "poll_response_autorenew.xml", ImmutableMap.of( - "ID", "1-C-EXAMPLE-13-16-2002", + "ID", "1-D-EXAMPLE-11-16-2002", "QDATE", "2002-06-01T00:04:00Z", "DOMAIN", "fakesite.example", "EXDATE", "2003-06-01T00:04:00Z")); - assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-C-EXAMPLE-13-16-2002")) + assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-D-EXAMPLE-11-16-2002")) .atTime("2002-07-01T00:02:00Z") .hasResponse("poll_ack_response_empty.xml"); @@ -769,13 +769,13 @@ class EppLifecycleDomainTest extends EppTestCase { .hasResponse( "poll_response_autorenew.xml", ImmutableMap.of( - "ID", "1-C-EXAMPLE-13-16-2003", // Note -- Year is different from previous ID. + "ID", "1-D-EXAMPLE-11-16-2003", // Note -- Year is different from previous ID. "QDATE", "2003-06-01T00:04:00Z", "DOMAIN", "fakesite.example", "EXDATE", "2004-06-01T00:04:00Z")); // Ack the second poll message and verify that none remain. - assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-C-EXAMPLE-13-16-2003")) + assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-D-EXAMPLE-11-16-2003")) .atTime("2003-07-01T00:05:05Z") .hasResponse("poll_ack_response_empty.xml"); assertThatCommand("poll.xml") @@ -805,7 +805,7 @@ class EppLifecycleDomainTest extends EppTestCase { // As the losing registrar, read the request poll message, and then ack it. assertThatLoginSucceeds("NewRegistrar", "foo-BAR2"); - String messageId = "1-C-EXAMPLE-18-24-2001"; + String messageId = "1-D-EXAMPLE-19-25-2001"; assertThatCommand("poll.xml") .atTime("2001-01-01T00:01:00Z") .hasResponse("poll_response_domain_transfer_request.xml", ImmutableMap.of("ID", messageId)); @@ -814,7 +814,7 @@ class EppLifecycleDomainTest extends EppTestCase { .hasResponse("poll_ack_response_empty.xml"); // Five days in the future, expect a server approval poll message to the loser, and ack it. - messageId = "1-C-EXAMPLE-18-23-2001"; + messageId = "1-D-EXAMPLE-19-24-2001"; assertThatCommand("poll.xml") .atTime("2001-01-06T00:01:00Z") .hasResponse( @@ -826,7 +826,7 @@ class EppLifecycleDomainTest extends EppTestCase { assertThatLogoutSucceeds(); // Also expect a server approval poll message to the winner, with the transfer request trid. - messageId = "1-C-EXAMPLE-18-22-2001"; + messageId = "1-D-EXAMPLE-19-23-2001"; assertThatLoginSucceeds("TheRegistrar", "password2"); assertThatCommand("poll.xml") .atTime("2001-01-06T00:02:00Z") diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferCancelFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferCancelFlowTest.java index 07cb6af93..13f519007 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferCancelFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferCancelFlowTest.java @@ -403,7 +403,7 @@ class DomainTransferCancelFlowTest persistResource( new DomainHistory.Builder() .setType(DOMAIN_TRANSFER_REQUEST) - .setParent(domain) + .setDomainContent(domain) .setModificationTime(clock.nowUtc().minusDays(4)) .setDomainTransactionRecords( ImmutableSet.of(previousSuccessRecord, notCancellableRecord)) diff --git a/core/src/test/java/google/registry/mapreduce/inputs/ChildEntityInputTest.java b/core/src/test/java/google/registry/mapreduce/inputs/ChildEntityInputTest.java index f8b2e886d..9e842a364 100644 --- a/core/src/test/java/google/registry/mapreduce/inputs/ChildEntityInputTest.java +++ b/core/src/test/java/google/registry/mapreduce/inputs/ChildEntityInputTest.java @@ -35,8 +35,10 @@ import google.registry.model.EppResource; import google.registry.model.ImmutableObject; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent.Reason; +import google.registry.model.contact.ContactHistory; import google.registry.model.contact.ContactResource; import google.registry.model.domain.DomainBase; +import google.registry.model.domain.DomainHistory; import google.registry.model.index.EppResourceIndex; import google.registry.model.reporting.HistoryEntry; import google.registry.testing.AppEngineExtension; @@ -64,9 +66,9 @@ class ChildEntityInputTest { private DomainBase domainA; private DomainBase domainB; - private HistoryEntry domainHistoryEntryA; - private HistoryEntry domainHistoryEntryB; - private HistoryEntry contactHistoryEntry; + private DomainHistory domainHistoryEntryA; + private DomainHistory domainHistoryEntryB; + private ContactHistory contactHistoryEntry; private BillingEvent.OneTime oneTimeA; private BillingEvent.OneTime oneTimeB; private BillingEvent.Recurring recurringA; @@ -78,10 +80,10 @@ class ChildEntityInputTest { domainA = persistEppResourceInFirstBucket(newDomainBase("a.tld", contact)); domainHistoryEntryA = persistResource( - new HistoryEntry.Builder().setParent(domainA).setModificationTime(now).build()); + new DomainHistory.Builder().setDomainContent(domainA).setModificationTime(now).build()); contactHistoryEntry = persistResource( - new HistoryEntry.Builder().setParent(contact).setModificationTime(now).build()); + new ContactHistory.Builder().setContactBase(contact).setModificationTime(now).build()); oneTimeA = persistResource( new BillingEvent.OneTime.Builder() @@ -111,7 +113,7 @@ class ChildEntityInputTest { domainB = persistEppResourceInFirstBucket(newDomainBase("b.tld")); domainHistoryEntryB = persistResource( - new HistoryEntry.Builder().setParent(domainB).setModificationTime(now).build()); + new DomainHistory.Builder().setDomainContent(domainB).setModificationTime(now).build()); oneTimeB = persistResource( new BillingEvent.OneTime.Builder() @@ -177,9 +179,9 @@ class ChildEntityInputTest { } assertThat(seen) .containsExactly( - domainHistoryEntryA, - domainHistoryEntryB, - contactHistoryEntry, + domainHistoryEntryA.asHistoryEntry(), + domainHistoryEntryB.asHistoryEntry(), + contactHistoryEntry.asHistoryEntry(), oneTimeA, recurringA, oneTimeB, @@ -202,7 +204,11 @@ class ChildEntityInputTest { .createReaders() .get(0); assertThat(getAllFromReader(reader)) - .containsExactly(domainHistoryEntryA, contactHistoryEntry, oneTimeA, recurringA); + .containsExactly( + domainHistoryEntryA.asHistoryEntry(), + contactHistoryEntry.asHistoryEntry(), + oneTimeA, + recurringA); } private static Set getAllFromReader(InputReader reader) @@ -230,7 +236,7 @@ class ChildEntityInputTest { HistoryEntry.class, BillingEvent.OneTime.class, BillingEvent.Recurring.class)) .createReaders() .get(0); - assertThat(getAllFromReader(reader)).containsExactly(contactHistoryEntry); + assertThat(getAllFromReader(reader)).containsExactly(contactHistoryEntry.asHistoryEntry()); } @Test @@ -287,11 +293,12 @@ class ChildEntityInputTest { DomainBase domain = persistSimpleResource(newDomainBase(i + ".tld")); historyEntries.add( persistResource( - new HistoryEntry.Builder() - .setParent(domain) - .setModificationTime(now) - .setClientId(i + ".tld") - .build())); + new DomainHistory.Builder() + .setDomainContent(domain) + .setModificationTime(now) + .setClientId(i + ".tld") + .build()) + .asHistoryEntry()); persistResource(EppResourceIndex.create(getBucketKey(i), Key.create(domain))); } Set seen = new HashSet<>(); @@ -333,7 +340,11 @@ class ChildEntityInputTest { seen.add(deserializedReader.next()); seen.add(deserializedReader.next()); assertThat(seen) - .containsExactly(domainHistoryEntryA, contactHistoryEntry, oneTimeA, recurringA); + .containsExactly( + domainHistoryEntryA.asHistoryEntry(), + contactHistoryEntry.asHistoryEntry(), + oneTimeA, + recurringA); assertThrows(NoSuchElementException.class, deserializedReader::next); } } diff --git a/core/src/test/java/google/registry/model/poll/PollMessageExternalKeyConverterTest.java b/core/src/test/java/google/registry/model/poll/PollMessageExternalKeyConverterTest.java index 2fca5cab0..9a0aed562 100644 --- a/core/src/test/java/google/registry/model/poll/PollMessageExternalKeyConverterTest.java +++ b/core/src/test/java/google/registry/model/poll/PollMessageExternalKeyConverterTest.java @@ -62,7 +62,7 @@ public class PollMessageExternalKeyConverterTest { historyEntry = persistResource( new DomainHistory.Builder() - .setParent(persistActiveDomain("foo.foobar")) + .setDomainContent(persistActiveDomain("foo.foobar")) .setType(HistoryEntry.Type.DOMAIN_CREATE) .setPeriod(Period.create(1, Period.Unit.YEARS)) .setXmlBytes("".getBytes(UTF_8)) diff --git a/core/src/test/java/google/registry/model/reporting/HistoryEntryDaoTest.java b/core/src/test/java/google/registry/model/reporting/HistoryEntryDaoTest.java index 788a0f055..e575b275e 100644 --- a/core/src/test/java/google/registry/model/reporting/HistoryEntryDaoTest.java +++ b/core/src/test/java/google/registry/model/reporting/HistoryEntryDaoTest.java @@ -41,7 +41,7 @@ import org.junit.jupiter.api.BeforeEach; class HistoryEntryDaoTest extends EntityTestCase { private DomainBase domain; - private HistoryEntry historyEntry; + private HistoryEntry domainHistory; @BeforeEach void beforeEach() { @@ -55,10 +55,10 @@ class HistoryEntryDaoTest extends EntityTestCase { .setReportField(TransactionReportField.NET_ADDS_1_YR) .setReportAmount(1) .build(); - // Set up a new persisted HistoryEntry entity. - historyEntry = + // Set up a new persisted DomainHistory entity. + domainHistory = new DomainHistory.Builder() - .setParent(domain) + .setDomainContent(domain) .setType(HistoryEntry.Type.DOMAIN_CREATE) .setPeriod(Period.create(1, Period.Unit.YEARS)) .setXmlBytes("".getBytes(UTF_8)) @@ -71,14 +71,14 @@ class HistoryEntryDaoTest extends EntityTestCase { .setRequestedByRegistrar(false) .setDomainTransactionRecords(ImmutableSet.of(transactionRecord)) .build(); - persistResource(historyEntry); + persistResource(domainHistory); } @TestOfyAndSql void testSimpleLoadAll() { assertThat(HistoryEntryDao.loadAllHistoryObjects(START_OF_TIME, END_OF_TIME)) - .comparingElementsUsing(immutableObjectCorrespondence("nsHosts")) - .containsExactly(historyEntry); + .comparingElementsUsing(immutableObjectCorrespondence("nsHosts", "domainContent")) + .containsExactly(domainHistory); } @TestOfyAndSql @@ -99,8 +99,8 @@ class HistoryEntryDaoTest extends EntityTestCase { transactIfJpaTm( () -> assertThat(HistoryEntryDao.loadHistoryObjectsForResource(domain.createVKey())) - .comparingElementsUsing(immutableObjectCorrespondence("nsHosts")) - .containsExactly(historyEntry)); + .comparingElementsUsing(immutableObjectCorrespondence("nsHosts", "domainContent")) + .containsExactly(domainHistory)); } @TestOfyAndSql diff --git a/core/src/test/java/google/registry/model/reporting/HistoryEntryTest.java b/core/src/test/java/google/registry/model/reporting/HistoryEntryTest.java index cb72526f7..781a5c61f 100644 --- a/core/src/test/java/google/registry/model/reporting/HistoryEntryTest.java +++ b/core/src/test/java/google/registry/model/reporting/HistoryEntryTest.java @@ -39,7 +39,7 @@ import org.junit.jupiter.api.BeforeEach; @DualDatabaseTest class HistoryEntryTest extends EntityTestCase { - private HistoryEntry historyEntry; + private DomainHistory domainHistory; @BeforeEach void setUp() { @@ -53,9 +53,9 @@ class HistoryEntryTest extends EntityTestCase { .setReportAmount(1) .build(); // Set up a new persisted HistoryEntry entity. - historyEntry = + domainHistory = new DomainHistory.Builder() - .setParent(domain) + .setDomainContent(domain) .setType(HistoryEntry.Type.DOMAIN_CREATE) .setPeriod(Period.create(1, Period.Unit.YEARS)) .setXmlBytes("".getBytes(UTF_8)) @@ -68,26 +68,27 @@ class HistoryEntryTest extends EntityTestCase { .setRequestedByRegistrar(false) .setDomainTransactionRecords(ImmutableSet.of(transactionRecord)) .build(); - persistResource(historyEntry); + persistResource(domainHistory); } @TestOfyAndSql void testPersistence() { transactIfJpaTm( () -> { - HistoryEntry fromDatabase = tm().loadByEntity(historyEntry); + HistoryEntry fromDatabase = tm().loadByEntity(domainHistory); assertAboutImmutableObjects() .that(fromDatabase) - .isEqualExceptFields(historyEntry, "nsHosts", "domainTransactionRecords"); + .isEqualExceptFields( + domainHistory, "nsHosts", "domainTransactionRecords", "domainContent"); assertAboutImmutableObjects() .that(Iterables.getOnlyElement(fromDatabase.getDomainTransactionRecords())) .isEqualExceptFields( - Iterables.getOnlyElement(historyEntry.getDomainTransactionRecords()), "id"); + Iterables.getOnlyElement(domainHistory.getDomainTransactionRecords()), "id"); }); } @TestOfyOnly void testIndexing() throws Exception { - verifyIndexing(historyEntry.asHistoryEntry(), "modificationTime", "clientId"); + verifyIndexing(domainHistory.asHistoryEntry(), "modificationTime", "clientId"); } } diff --git a/core/src/test/java/google/registry/rde/DomainBaseToXjcConverterTest.java b/core/src/test/java/google/registry/rde/DomainBaseToXjcConverterTest.java index 5787be2a5..e655b7774 100644 --- a/core/src/test/java/google/registry/rde/DomainBaseToXjcConverterTest.java +++ b/core/src/test/java/google/registry/rde/DomainBaseToXjcConverterTest.java @@ -224,7 +224,7 @@ public class DomainBaseToXjcConverterTest { new DomainHistory.Builder() .setModificationTime(clock.nowUtc()) .setType(HistoryEntry.Type.DOMAIN_CREATE) - .setParent(domain) + .setDomainContent(domain) .build()); BillingEvent.OneTime billingEvent = persistResource( diff --git a/core/src/test/java/google/registry/testing/DatabaseHelper.java b/core/src/test/java/google/registry/testing/DatabaseHelper.java index 0b1024d2e..39ae69a62 100644 --- a/core/src/test/java/google/registry/testing/DatabaseHelper.java +++ b/core/src/test/java/google/registry/testing/DatabaseHelper.java @@ -64,7 +64,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Streams; import com.google.common.net.InetAddresses; import com.googlecode.objectify.Key; -import com.googlecode.objectify.cmd.Saver; import google.registry.dns.writer.VoidDnsWriter; import google.registry.model.Buildable; import google.registry.model.EppResource; @@ -124,6 +123,7 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Optional; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Function; import javax.annotation.Nullable; import org.hibernate.Hibernate; @@ -642,7 +642,7 @@ public class DatabaseHelper { new DomainHistory.Builder() .setType(HistoryEntry.Type.DOMAIN_CREATE) .setModificationTime(now) - .setParent(domain) + .setDomainContent(domain) .build()); BillingEvent.Recurring autorenewEvent = persistResource( @@ -683,7 +683,7 @@ public class DatabaseHelper { new DomainHistory.Builder() .setType(HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST) .setModificationTime(tm().transact(() -> tm().getTransactionTime())) - .setParent(domain) + .setDomainContent(domain) .build()); BillingEvent.OneTime transferBillingEvent = persistResource( @@ -1014,8 +1014,9 @@ public class DatabaseHelper { private static void saveResource(R resource, boolean wantBackup) { if (tm().isOfy()) { - Saver saver = wantBackup || alwaysSaveWithBackup ? ofy().save() : ofy().saveWithoutBackup(); - saver.entity(resource); + Consumer saver = + wantBackup || alwaysSaveWithBackup ? tm()::put : tm()::putWithoutBackup; + saver.accept(resource); if (resource instanceof EppResource) { EppResource eppResource = (EppResource) resource; persistEppResourceExtras( @@ -1027,13 +1028,13 @@ public class DatabaseHelper { } private static void persistEppResourceExtras( - R resource, EppResourceIndex index, Saver saver) { + R resource, EppResourceIndex index, Consumer saver) { assertWithMessage("Cannot persist an EppResource with a missing repoId in tests") .that(resource.getRepoId()) .isNotEmpty(); - saver.entity(index); + saver.accept(index); if (resource instanceof ForeignKeyedEppResource) { - saver.entity(ForeignKeyIndex.create(resource, resource.getDeletionTime())); + saver.accept(ForeignKeyIndex.create(resource, resource.getDeletionTime())); } } @@ -1058,8 +1059,8 @@ public class DatabaseHelper { tm().transact( () -> { if (tm().isOfy()) { - Saver saver = ofy().save(); - saver.entity(resource); + Consumer saver = tm()::put; + saver.accept(resource); persistEppResourceExtras(resource, eppResourceIndex, saver); } else { tm().put(resource); diff --git a/core/src/test/java/google/registry/tools/DedupeRecurringBillingEventIdsCommandTest.java b/core/src/test/java/google/registry/tools/DedupeRecurringBillingEventIdsCommandTest.java index dc5567f3c..e4328beba 100644 --- a/core/src/test/java/google/registry/tools/DedupeRecurringBillingEventIdsCommandTest.java +++ b/core/src/test/java/google/registry/tools/DedupeRecurringBillingEventIdsCommandTest.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.testing.DatabaseHelper.createTld; +import static google.registry.testing.DatabaseHelper.loadByEntity; import static google.registry.testing.DatabaseHelper.persistActiveDomain; import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.util.DateTimeUtils.END_OF_TIME; @@ -225,7 +226,7 @@ class DedupeRecurringBillingEventIdsCommandTest private static void assertNotChangeExceptUpdateTime(ImmutableObject... entities) { for (ImmutableObject entity : entities) { assertAboutImmutableObjects() - .that(ofy().load().entity(entity).now()) + .that(loadByEntity(entity)) .isEqualExceptFields(entity, "updateTimestamp", "revisions"); } } diff --git a/core/src/test/java/google/registry/tools/EppLifecycleToolsTest.java b/core/src/test/java/google/registry/tools/EppLifecycleToolsTest.java index 854f2928a..c76a4100f 100644 --- a/core/src/test/java/google/registry/tools/EppLifecycleToolsTest.java +++ b/core/src/test/java/google/registry/tools/EppLifecycleToolsTest.java @@ -108,7 +108,7 @@ class EppLifecycleToolsTest extends EppTestCase { .atTime("2001-06-08T00:00:00Z") .hasResponse("poll_response_unrenew.xml"); - assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-8-TLD-19-20-2001")) + assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-9-TLD-20-21-2001")) .atTime("2001-06-08T00:00:01Z") .hasResponse("poll_ack_response_empty.xml"); @@ -129,7 +129,7 @@ class EppLifecycleToolsTest extends EppTestCase { .hasResponse( "poll_response_autorenew.xml", ImmutableMap.of( - "ID", "1-8-TLD-19-22-2003", + "ID", "1-9-TLD-20-23-2003", "QDATE", "2003-06-01T00:02:00Z", "DOMAIN", "example.tld", "EXDATE", "2004-06-01T00:02:00Z")); diff --git a/core/src/test/java/google/registry/tools/UpdateDomainCommandTest.java b/core/src/test/java/google/registry/tools/UpdateDomainCommandTest.java index e8eaf8650..13e1368e8 100644 --- a/core/src/test/java/google/registry/tools/UpdateDomainCommandTest.java +++ b/core/src/test/java/google/registry/tools/UpdateDomainCommandTest.java @@ -298,7 +298,7 @@ class UpdateDomainCommandTest extends EppToolCommandTestCase Command completed successfully; ack to dequeue - + 2001-06-07T00:00:00Z Domain example.tld was unrenewed by 3 years; now expires at 2003-06-01T00:02:00.000Z. diff --git a/core/src/test/resources/google/registry/model/schema.txt b/core/src/test/resources/google/registry/model/schema.txt index e723ad266..ace79d5eb 100644 --- a/core/src/test/resources/google/registry/model/schema.txt +++ b/core/src/test/resources/google/registry/model/schema.txt @@ -294,8 +294,8 @@ class google.registry.model.domain.GracePeriod { google.registry.model.domain.rgp.GracePeriodStatus type; google.registry.persistence.BillingVKey$BillingEventVKey billingEventOneTime; google.registry.persistence.BillingVKey$BillingRecurrenceVKey billingEventRecurring; - java.lang.Long gracePeriodId; java.lang.String clientId; + long gracePeriodId; org.joda.time.DateTime expirationTime; } class google.registry.model.domain.Period {