mirror of
https://github.com/google/nomulus.git
synced 2025-04-29 19:47:51 +02:00
Make entities serializable for DB validation (#1401)
* Make entities serializable for DB validation Make entities that are asynchronously replicated between Datastore and Cloud SQL serializable so that they may be used in BEAM pipeline based comparison tool. Introduced an UnsafeSerializable interface (extending Serializable) and added to relevant classes. Implementing classes are allowed some shortcuts as explained in the interface's Javadoc. Post migration we will decide whether to revert this change or properly implement serialization. Verified with production data.
This commit is contained in:
parent
0d5b436b41
commit
0978ede5d9
47 changed files with 333 additions and 62 deletions
|
@ -501,7 +501,8 @@ task javadoc(type: Javadoc) {
|
|||
options.addBooleanOption('Xdoclint:all,-missing', true)
|
||||
options.addBooleanOption("-allow-script-in-comments",true)
|
||||
options.tags = ["type:a:Generic Type",
|
||||
"error:a:Expected Error"]
|
||||
"error:a:Expected Error",
|
||||
"invariant:a:Guaranteed Property"]
|
||||
}
|
||||
|
||||
tasks.build.dependsOn(tasks.javadoc)
|
||||
|
|
|
@ -31,7 +31,7 @@ import javax.xml.bind.annotation.XmlTransient;
|
|||
* that we can enforce strictly increasing timestamps.
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class BackupGroupRoot extends ImmutableObject {
|
||||
public abstract class BackupGroupRoot extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
/**
|
||||
* An automatically managed timestamp of when this object was last written to Datastore.
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.joda.time.DateTime;
|
|||
*
|
||||
* @see CreateAutoTimestampTranslatorFactory
|
||||
*/
|
||||
public class CreateAutoTimestamp extends ImmutableObject {
|
||||
public class CreateAutoTimestamp extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
DateTime timestamp;
|
||||
|
||||
|
|
|
@ -85,6 +85,9 @@ public abstract class ImmutableObject implements Cloneable {
|
|||
@Target(FIELD)
|
||||
public @interface Insignificant {}
|
||||
|
||||
// Note: if this class is made to implement Serializable, this field must become 'transient' since
|
||||
// hashing is not stable across executions. Also note that @XmlTransient is forbidden on transient
|
||||
// fields and need to be removed if transient is added.
|
||||
@Ignore @XmlTransient protected Integer hashCode;
|
||||
|
||||
private boolean equalsImmutableObject(ImmutableObject other) {
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2021 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Marker interface for Nomulus entities whose serialization are implemented in a fragile way. These
|
||||
* entities are made {@link Serializable} so that they can be passed between JVMs. The intended use
|
||||
* case is BEAM pipeline-based cross-database data validation between Datastore and Cloud SQL during
|
||||
* the migration. Note that only objects loaded from the SQL database need serialization support.
|
||||
* Objects exported from Datastore can already be serialized as protocol buffers.
|
||||
*
|
||||
* <p>All entities implementing this interface take advantage of the fact that all Java collection
|
||||
* classes we use, either directly or indirectly, including those in Java libraries, Guava,
|
||||
* Objectify, and Hibernate are {@code Serializable}.
|
||||
*
|
||||
* <p>The {@code serialVersionUID} field has also been omitted in the implementing classes, since
|
||||
* they are not used for persistence.
|
||||
*/
|
||||
// TODO(b/203609782): either remove this interface or fix implementors post migration.
|
||||
public interface UnsafeSerializable extends Serializable {}
|
|
@ -38,7 +38,7 @@ import org.joda.time.DateTime;
|
|||
* @see UpdateAutoTimestampTranslatorFactory
|
||||
*/
|
||||
@Embeddable
|
||||
public class UpdateAutoTimestamp extends ImmutableObject {
|
||||
public class UpdateAutoTimestamp extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
// When set to true, database converters/translators should do the auto update. When set to
|
||||
// false, auto update should be suspended (this exists to allow us to preserve the original value
|
||||
|
|
|
@ -39,6 +39,7 @@ import com.googlecode.objectify.annotation.Parent;
|
|||
import com.googlecode.objectify.condition.IfNull;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.common.TimeOfYear;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
|
@ -72,7 +73,7 @@ import org.joda.time.DateTime;
|
|||
/** A billable event in a domain's lifecycle. */
|
||||
@MappedSuperclass
|
||||
public abstract class BillingEvent extends ImmutableObject
|
||||
implements Buildable, TransferServerApproveEntity {
|
||||
implements Buildable, TransferServerApproveEntity, UnsafeSerializable {
|
||||
|
||||
/** The reason for the bill, which maps 1:1 to skus in go/registry-billing-skus. */
|
||||
public enum Reason {
|
||||
|
|
|
@ -27,13 +27,13 @@ import com.googlecode.objectify.annotation.Ignore;
|
|||
import com.googlecode.objectify.annotation.OnLoad;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.model.annotations.InCrossTld;
|
||||
import google.registry.model.common.Cursor.CursorId;
|
||||
import google.registry.model.replay.DatastoreAndSqlEntity;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.Column;
|
||||
|
@ -53,7 +53,7 @@ import org.joda.time.DateTime;
|
|||
@javax.persistence.Entity
|
||||
@IdClass(CursorId.class)
|
||||
@InCrossTld
|
||||
public class Cursor extends ImmutableObject implements DatastoreAndSqlEntity {
|
||||
public class Cursor extends ImmutableObject implements DatastoreAndSqlEntity, UnsafeSerializable {
|
||||
|
||||
/** The scope of a global cursor. A global cursor is a cursor that is not specific to one tld. */
|
||||
public static final String GLOBAL = "GLOBAL";
|
||||
|
@ -283,7 +283,7 @@ public class Cursor extends ImmutableObject implements DatastoreAndSqlEntity {
|
|||
return cursorTime;
|
||||
}
|
||||
|
||||
static class CursorId extends ImmutableObject implements Serializable {
|
||||
public static class CursorId extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
public CursorType type;
|
||||
public String scope;
|
||||
|
|
|
@ -28,6 +28,7 @@ import com.google.common.collect.Range;
|
|||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import java.util.List;
|
||||
import javax.persistence.Embeddable;
|
||||
import org.joda.time.DateTime;
|
||||
|
@ -45,7 +46,7 @@ import org.joda.time.DateTime;
|
|||
*/
|
||||
@Embed
|
||||
@Embeddable
|
||||
public class TimeOfYear extends ImmutableObject {
|
||||
public class TimeOfYear extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
/**
|
||||
* The time as "month day millis" with all fields left-padded with zeroes so that lexographic
|
||||
|
|
|
@ -27,7 +27,9 @@ import com.google.common.collect.Maps;
|
|||
import com.google.common.collect.Ordering;
|
||||
import com.googlecode.objectify.mapper.Mapper;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.util.TypeUtils;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
@ -53,11 +55,12 @@ import org.joda.time.DateTime;
|
|||
* to use for storing the list of transitions. The user is given this choice of subclass so that the
|
||||
* field of the value type stored in the transition can be given a customized name.
|
||||
*/
|
||||
public class TimedTransitionProperty<V, T extends TimedTransitionProperty.TimedTransition<V>>
|
||||
extends ForwardingMap<DateTime, T> {
|
||||
public class TimedTransitionProperty<
|
||||
V extends Serializable, T extends TimedTransitionProperty.TimedTransition<V>>
|
||||
extends ForwardingMap<DateTime, T> implements UnsafeSerializable {
|
||||
|
||||
/**
|
||||
* A transition to a value of type {@code V} at a certain time. This superclass only has a field
|
||||
* A transition to a value of type {@code V} at a certain time. This superclass only has a field
|
||||
* for the {@code DateTime}, which means that subclasses should supply the field of type {@code V}
|
||||
* and implementations of the abstract getter and setter methods to access that field. This design
|
||||
* is so that subclasses tagged with @Embed can define a custom field name for their value, for
|
||||
|
@ -65,11 +68,12 @@ public class TimedTransitionProperty<V, T extends TimedTransitionProperty.TimedT
|
|||
*
|
||||
* <p>The public visibility of this class exists only so that it can be subclassed; clients should
|
||||
* never call any methods on this class or attempt to access its members, but should instead treat
|
||||
* it as a customizable implementation detail of {@code TimedTransitionProperty}. However, note
|
||||
* it as a customizable implementation detail of {@code TimedTransitionProperty}. However, note
|
||||
* that subclasses must also have public visibility so that they can be instantiated via
|
||||
* reflection in a call to {@code fromValueMap}.
|
||||
*/
|
||||
public abstract static class TimedTransition<V> extends ImmutableObject {
|
||||
public abstract static class TimedTransition<V extends Serializable> extends ImmutableObject
|
||||
implements UnsafeSerializable {
|
||||
/** The time at which this value becomes the active value. */
|
||||
private DateTime transitionTime;
|
||||
|
||||
|
@ -89,16 +93,16 @@ public class TimedTransitionProperty<V, T extends TimedTransitionProperty.TimedT
|
|||
}
|
||||
|
||||
/**
|
||||
* Converts the provided value map into the equivalent transition map, using transition objects
|
||||
* of the given TimedTransition subclass. The value map must be sorted according to the natural
|
||||
* Converts the provided value map into the equivalent transition map, using transition objects of
|
||||
* the given TimedTransition subclass. The value map must be sorted according to the natural
|
||||
* ordering of its DateTime keys, and keys cannot be earlier than START_OF_TIME.
|
||||
*/
|
||||
// NB: The Class<T> parameter could be eliminated by getting the class via reflection, but then
|
||||
// the callsite cannot infer T, so unless you explicitly call this as .<V, T>fromValueMap() it
|
||||
// will default to using just TimedTransition<V>, which fails at runtime.
|
||||
private static <V, T extends TimedTransition<V>> NavigableMap<DateTime, T> makeTransitionMap(
|
||||
ImmutableSortedMap<DateTime, V> valueMap,
|
||||
final Class<T> timedTransitionSubclass) {
|
||||
private static <V extends Serializable, T extends TimedTransition<V>>
|
||||
NavigableMap<DateTime, T> makeTransitionMap(
|
||||
ImmutableSortedMap<DateTime, V> valueMap, final Class<T> timedTransitionSubclass) {
|
||||
checkArgument(
|
||||
Ordering.natural().equals(valueMap.comparator()),
|
||||
"Timed transition value map must have transition time keys in chronological order");
|
||||
|
@ -121,9 +125,9 @@ public class TimedTransitionProperty<V, T extends TimedTransitionProperty.TimedT
|
|||
*
|
||||
* <p>This method should be the normal method for constructing a {@link TimedTransitionProperty}.
|
||||
*/
|
||||
public static <V, T extends TimedTransition<V>> TimedTransitionProperty<V, T> fromValueMap(
|
||||
ImmutableSortedMap<DateTime, V> valueMap,
|
||||
final Class<T> timedTransitionSubclass) {
|
||||
public static <V extends Serializable, T extends TimedTransition<V>>
|
||||
TimedTransitionProperty<V, T> fromValueMap(
|
||||
ImmutableSortedMap<DateTime, V> valueMap, final Class<T> timedTransitionSubclass) {
|
||||
return new TimedTransitionProperty<>(ImmutableSortedMap.copyOf(
|
||||
makeTransitionMap(valueMap, timedTransitionSubclass)));
|
||||
}
|
||||
|
@ -175,10 +179,10 @@ public class TimedTransitionProperty<V, T extends TimedTransitionProperty.TimedT
|
|||
* @param allowedTransitions optional map of all possible state-to-state transitions
|
||||
* @param allowedTransitionMapName optional transition map description string for error messages
|
||||
* @param initialValue optional initial value; if present, the first transition must have this
|
||||
* value
|
||||
* value
|
||||
* @param badInitialValueErrorMessage option error message string if the initial value is wrong
|
||||
*/
|
||||
public static <V, T extends TimedTransitionProperty.TimedTransition<V>>
|
||||
public static <V extends Serializable, T extends TimedTransitionProperty.TimedTransition<V>>
|
||||
TimedTransitionProperty<V, T> make(
|
||||
ImmutableSortedMap<DateTime, V> newTransitions,
|
||||
Class<T> transitionClass,
|
||||
|
@ -200,7 +204,7 @@ public class TimedTransitionProperty<V, T extends TimedTransitionProperty.TimedT
|
|||
* Validates that a transition map is not null or empty, starts at START_OF_TIME, and has
|
||||
* transitions which move from one value to another in allowed ways.
|
||||
*/
|
||||
public static <V, T extends TimedTransitionProperty.TimedTransition<V>>
|
||||
public static <V extends Serializable, T extends TimedTransitionProperty.TimedTransition<V>>
|
||||
void validateTimedTransitionMap(
|
||||
@Nullable NavigableMap<DateTime, V> transitionMap,
|
||||
ImmutableMultimap<V, V> allowedTransitions,
|
||||
|
@ -240,8 +244,9 @@ public class TimedTransitionProperty<V, T extends TimedTransitionProperty.TimedT
|
|||
* annotation. The map for those fields must be mutable so that Objectify can load values from
|
||||
* Datastore into the map, but clients should still never mutate the field's map directly.
|
||||
*/
|
||||
public static <V, T extends TimedTransition<V>> TimedTransitionProperty<V, T> forMapify(
|
||||
ImmutableSortedMap<DateTime, V> valueMap, Class<T> timedTransitionSubclass) {
|
||||
public static <V extends Serializable, T extends TimedTransition<V>>
|
||||
TimedTransitionProperty<V, T> forMapify(
|
||||
ImmutableSortedMap<DateTime, V> valueMap, Class<T> timedTransitionSubclass) {
|
||||
return new TimedTransitionProperty<>(
|
||||
new TreeMap<>(makeTransitionMap(valueMap, timedTransitionSubclass)));
|
||||
}
|
||||
|
@ -254,8 +259,9 @@ public class TimedTransitionProperty<V, T extends TimedTransitionProperty.TimedT
|
|||
* annotation. The map for those fields must be mutable so that Objectify can load values from
|
||||
* Datastore into the map, but clients should still never mutate the field's map directly.
|
||||
*/
|
||||
public static <V, T extends TimedTransition<V>> TimedTransitionProperty<V, T> forMapify(
|
||||
V valueAtStartOfTime, Class<T> timedTransitionSubclass) {
|
||||
public static <V extends Serializable, T extends TimedTransition<V>>
|
||||
TimedTransitionProperty<V, T> forMapify(
|
||||
V valueAtStartOfTime, Class<T> timedTransitionSubclass) {
|
||||
return forMapify(
|
||||
ImmutableSortedMap.of(START_OF_TIME, valueAtStartOfTime), timedTransitionSubclass);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.googlecode.objectify.Key;
|
|||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.contact.ContactHistory.ContactHistoryId;
|
||||
import google.registry.model.replay.DatastoreEntity;
|
||||
import google.registry.model.replay.SqlEntity;
|
||||
|
@ -59,7 +60,7 @@ import javax.persistence.PostLoad;
|
|||
@EntitySubclass
|
||||
@Access(AccessType.FIELD)
|
||||
@IdClass(ContactHistoryId.class)
|
||||
public class ContactHistory extends HistoryEntry implements SqlEntity {
|
||||
public class ContactHistory extends HistoryEntry implements SqlEntity, UnsafeSerializable {
|
||||
|
||||
// Store ContactBase instead of ContactResource so we don't pick up its @Id
|
||||
// Nullable for the sake of pre-Registry-3.0 history objects
|
||||
|
|
|
@ -20,7 +20,9 @@ import com.google.common.collect.ImmutableList;
|
|||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.eppcommon.PresenceMarker;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
|
@ -31,7 +33,7 @@ import javax.xml.bind.annotation.XmlType;
|
|||
@Embed
|
||||
@Embeddable
|
||||
@XmlType(propOrder = {"name", "org", "addr", "voice", "fax", "email"})
|
||||
public class Disclose extends ImmutableObject {
|
||||
public class Disclose extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
List<PostalInfoChoice> name;
|
||||
|
||||
|
@ -78,7 +80,7 @@ public class Disclose extends ImmutableObject {
|
|||
|
||||
/** The "intLocType" from <a href="http://tools.ietf.org/html/rfc5733">RFC5733</a>. */
|
||||
@Embed
|
||||
public static class PostalInfoChoice extends ImmutableObject {
|
||||
public static class PostalInfoChoice extends ImmutableObject implements Serializable {
|
||||
@XmlAttribute
|
||||
PostalInfo.Type type;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.googlecode.objectify.annotation.Embed;
|
|||
import google.registry.model.Buildable;
|
||||
import google.registry.model.Buildable.Overlayable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EnumType;
|
||||
|
@ -38,7 +39,8 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
|||
@Embed
|
||||
@Embeddable
|
||||
@XmlType(propOrder = {"name", "org", "address", "type"})
|
||||
public class PostalInfo extends ImmutableObject implements Overlayable<PostalInfo> {
|
||||
public class PostalInfo extends ImmutableObject
|
||||
implements Overlayable<PostalInfo>, UnsafeSerializable {
|
||||
|
||||
/** The type of the address, either localized or international. */
|
||||
public enum Type {
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.googlecode.objectify.annotation.Embed;
|
|||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.persistence.VKey;
|
||||
import javax.persistence.Embeddable;
|
||||
|
@ -46,7 +47,7 @@ import javax.xml.bind.annotation.XmlEnumValue;
|
|||
*/
|
||||
@Embed
|
||||
@Embeddable
|
||||
public class DesignatedContact extends ImmutableObject {
|
||||
public class DesignatedContact extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
/**
|
||||
* XML type for contact types. This can be either: {@code "admin"}, {@code "billing"}, or
|
||||
|
|
|
@ -17,6 +17,7 @@ package google.registry.model.domain;
|
|||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.persistence.BillingVKey.BillingEventVKey;
|
||||
|
@ -35,7 +36,7 @@ import org.joda.time.DateTime;
|
|||
@Embed
|
||||
@MappedSuperclass
|
||||
@Access(AccessType.FIELD)
|
||||
public class GracePeriodBase extends ImmutableObject {
|
||||
public class GracePeriodBase extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
/** Unique id required for hibernate representation. */
|
||||
@Transient long gracePeriodId;
|
||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.model.domain;
|
|||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
@ -25,7 +26,7 @@ import javax.xml.bind.annotation.XmlValue;
|
|||
/** The "periodType" from <a href="http://tools.ietf.org/html/rfc5731">RFC5731</a>. */
|
||||
@Embed
|
||||
@javax.persistence.Embeddable
|
||||
public class Period extends ImmutableObject {
|
||||
public class Period extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@XmlAttribute
|
||||
|
|
|
@ -27,6 +27,7 @@ import com.googlecode.objectify.annotation.Embed;
|
|||
import com.googlecode.objectify.annotation.IgnoreSave;
|
||||
import com.googlecode.objectify.condition.IfNull;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
@ -39,7 +40,7 @@ import org.joda.time.DateTime;
|
|||
@Embed
|
||||
@XmlType(propOrder = {"noticeId", "expirationTime", "acceptedTime"})
|
||||
@javax.persistence.Embeddable
|
||||
public class LaunchNotice extends ImmutableObject {
|
||||
public class LaunchNotice extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
/** An empty instance to use in place of null. */
|
||||
private static final NoticeIdType EMPTY_NOTICE_ID = new NoticeIdType();
|
||||
|
@ -47,14 +48,13 @@ public class LaunchNotice extends ImmutableObject {
|
|||
/** An id with a validator-id attribute. */
|
||||
@Embed
|
||||
@javax.persistence.Embeddable
|
||||
public static class NoticeIdType extends ImmutableObject {
|
||||
public static class NoticeIdType extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
/**
|
||||
* The Trademark Claims Notice ID from
|
||||
* {@link "http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.3"}.
|
||||
* The Trademark Claims Notice ID from <a
|
||||
* href="http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.3">the RFC</a>.
|
||||
*/
|
||||
@XmlValue
|
||||
String tcnId;
|
||||
@XmlValue String tcnId;
|
||||
|
||||
/** The identifier of the TMDB provider to use, defaulting to the TMCH. */
|
||||
@IgnoreSave(IfNull.class)
|
||||
|
|
|
@ -17,6 +17,7 @@ package google.registry.model.domain.secdns;
|
|||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
@ -31,7 +32,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
|||
@Embed
|
||||
@MappedSuperclass
|
||||
@Access(AccessType.FIELD)
|
||||
public abstract class DomainDsDataBase extends ImmutableObject {
|
||||
public abstract class DomainDsDataBase extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
@Ignore @XmlTransient @Transient String domainRepoId;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.model.domain.secdns;
|
|||
|
||||
import static google.registry.model.IdService.allocateId;
|
||||
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.replay.SqlOnlyEntity;
|
||||
|
@ -27,7 +28,8 @@ import javax.persistence.Id;
|
|||
|
||||
/** Entity class to represent a historic {@link DelegationSignerData}. */
|
||||
@Entity
|
||||
public class DomainDsDataHistory extends DomainDsDataBase implements SqlOnlyEntity {
|
||||
public class DomainDsDataHistory extends DomainDsDataBase
|
||||
implements SqlOnlyEntity, UnsafeSerializable {
|
||||
|
||||
@Id Long dsDataHistoryRevisionId;
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import google.registry.model.Buildable;
|
|||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.JsonMapBuilder;
|
||||
import google.registry.model.Jsonifiable;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
@ -56,7 +57,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
|||
@XmlTransient
|
||||
@Embeddable
|
||||
@MappedSuperclass
|
||||
public class Address extends ImmutableObject implements Jsonifiable {
|
||||
public class Address extends ImmutableObject implements Jsonifiable, UnsafeSerializable {
|
||||
|
||||
/** The schema validation will enforce that this has 3 lines at most. */
|
||||
// TODO(b/177569726): Remove this field after migration. We need to figure out how to generate
|
||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.model.eppcommon;
|
|||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
@ -35,7 +36,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
|||
@XmlTransient
|
||||
@Embeddable
|
||||
@MappedSuperclass
|
||||
public abstract class AuthInfo extends ImmutableObject {
|
||||
public abstract class AuthInfo extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
@Embedded protected PasswordAuth pw;
|
||||
|
||||
|
@ -47,7 +48,7 @@ public abstract class AuthInfo extends ImmutableObject {
|
|||
@Embed
|
||||
@XmlType(namespace = "urn:ietf:params:xml:ns:eppcom-1.0")
|
||||
@Embeddable
|
||||
public static class PasswordAuth extends ImmutableObject {
|
||||
public static class PasswordAuth extends ImmutableObject implements UnsafeSerializable {
|
||||
@XmlValue
|
||||
@XmlJavaTypeAdapter(NormalizedStringAdapter.class)
|
||||
String value;
|
||||
|
|
|
@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
@ -49,7 +50,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
|||
@XmlTransient
|
||||
@Embeddable
|
||||
@MappedSuperclass
|
||||
public class PhoneNumber extends ImmutableObject {
|
||||
public class PhoneNumber extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
@XmlValue
|
||||
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
|
||||
|
|
|
@ -18,6 +18,7 @@ import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
|||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
@ -32,7 +33,7 @@ import javax.xml.bind.annotation.XmlType;
|
|||
@Embed
|
||||
@XmlType(propOrder = {"clientTransactionId", "serverTransactionId"})
|
||||
@javax.persistence.Embeddable
|
||||
public class Trid extends ImmutableObject {
|
||||
public class Trid extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
/** The server transaction id. */
|
||||
@XmlElement(name = "svTRID", namespace = "urn:ietf:params:xml:ns:epp-1.0")
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.googlecode.objectify.Key;
|
|||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.host.HostHistory.HostHistoryId;
|
||||
import google.registry.model.replay.DatastoreEntity;
|
||||
import google.registry.model.replay.SqlEntity;
|
||||
|
@ -60,7 +61,7 @@ import javax.persistence.PostLoad;
|
|||
@EntitySubclass
|
||||
@Access(AccessType.FIELD)
|
||||
@IdClass(HostHistoryId.class)
|
||||
public class HostHistory extends HistoryEntry implements SqlEntity {
|
||||
public class HostHistory extends HistoryEntry implements SqlEntity, UnsafeSerializable {
|
||||
|
||||
// Store HostBase instead of HostResource so we don't pick up its @Id
|
||||
// Nullable for the sake of pre-Registry-3.0 history objects
|
||||
|
|
|
@ -17,6 +17,7 @@ package google.registry.model.poll;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.eppoutput.EppResponse.ResponseData;
|
||||
import javax.persistence.Embeddable;
|
||||
|
@ -31,12 +32,13 @@ import org.joda.time.DateTime;
|
|||
/** The {@link ResponseData} returned when completing a pending action on a domain. */
|
||||
@XmlTransient
|
||||
@Embeddable
|
||||
public class PendingActionNotificationResponse extends ImmutableObject implements ResponseData {
|
||||
public class PendingActionNotificationResponse extends ImmutableObject
|
||||
implements ResponseData, UnsafeSerializable {
|
||||
|
||||
/** The inner name type that contains a name and the result boolean. */
|
||||
@Embed
|
||||
@Embeddable
|
||||
static class NameOrId extends ImmutableObject {
|
||||
static class NameOrId extends ImmutableObject implements UnsafeSerializable {
|
||||
@XmlValue
|
||||
String value;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import com.googlecode.objectify.annotation.Parent;
|
|||
import google.registry.model.Buildable;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.annotations.ExternalMessagingName;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
|
@ -98,7 +99,7 @@ import org.joda.time.DateTime;
|
|||
@javax.persistence.Index(columnList = "eventTime")
|
||||
})
|
||||
public abstract class PollMessage extends ImmutableObject
|
||||
implements Buildable, DatastoreAndSqlEntity, TransferServerApproveEntity {
|
||||
implements Buildable, DatastoreAndSqlEntity, TransferServerApproveEntity, UnsafeSerializable {
|
||||
|
||||
/** Entity id. */
|
||||
@Id
|
||||
|
|
|
@ -72,6 +72,7 @@ import google.registry.model.CreateAutoTimestamp;
|
|||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.JsonMapBuilder;
|
||||
import google.registry.model.Jsonifiable;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.model.annotations.InCrossTld;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
|
@ -116,7 +117,7 @@ import org.joda.time.DateTime;
|
|||
})
|
||||
@InCrossTld
|
||||
public class Registrar extends ImmutableObject
|
||||
implements Buildable, DatastoreAndSqlEntity, Jsonifiable {
|
||||
implements Buildable, DatastoreAndSqlEntity, Jsonifiable, UnsafeSerializable {
|
||||
|
||||
/** Represents the type of a registrar entity. */
|
||||
public enum Type {
|
||||
|
@ -404,7 +405,7 @@ public class Registrar extends ImmutableObject
|
|||
|
||||
/** A billing account entry for this registrar, consisting of a currency and an account Id. */
|
||||
@Embed
|
||||
public static class BillingAccountEntry extends ImmutableObject {
|
||||
public static class BillingAccountEntry extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
CurrencyUnit currency;
|
||||
String accountId;
|
||||
|
|
|
@ -46,6 +46,7 @@ import google.registry.model.Buildable;
|
|||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.JsonMapBuilder;
|
||||
import google.registry.model.Jsonifiable;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.annotations.InCrossTld;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.registrar.RegistrarContact.RegistrarPocId;
|
||||
|
@ -82,7 +83,7 @@ import javax.persistence.Transient;
|
|||
@IdClass(RegistrarPocId.class)
|
||||
@InCrossTld
|
||||
public class RegistrarContact extends ImmutableObject
|
||||
implements DatastoreAndSqlEntity, Jsonifiable {
|
||||
implements DatastoreAndSqlEntity, Jsonifiable, UnsafeSerializable {
|
||||
|
||||
@Parent @Transient Key<Registrar> parent;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import com.googlecode.objectify.annotation.Embed;
|
|||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.replay.DatastoreAndSqlEntity;
|
||||
import javax.persistence.Column;
|
||||
|
@ -46,7 +47,7 @@ import org.joda.time.DateTime;
|
|||
@Embed
|
||||
@Entity
|
||||
public class DomainTransactionRecord extends ImmutableObject
|
||||
implements Buildable, DatastoreAndSqlEntity {
|
||||
implements Buildable, DatastoreAndSqlEntity, UnsafeSerializable {
|
||||
|
||||
@Id
|
||||
@Ignore
|
||||
|
|
|
@ -31,6 +31,7 @@ import com.googlecode.objectify.condition.IfNull;
|
|||
import google.registry.model.Buildable;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.contact.ContactBase;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
|
@ -83,7 +84,8 @@ import org.joda.time.DateTime;
|
|||
@Entity
|
||||
@MappedSuperclass
|
||||
@Access(AccessType.FIELD)
|
||||
public class HistoryEntry extends ImmutableObject implements Buildable, DatastoreEntity {
|
||||
public class HistoryEntry extends ImmutableObject
|
||||
implements Buildable, DatastoreEntity, UnsafeSerializable {
|
||||
|
||||
/** Represents the type of history entry. */
|
||||
public enum Type {
|
||||
|
|
|
@ -52,6 +52,7 @@ import com.googlecode.objectify.annotation.Parent;
|
|||
import google.registry.model.Buildable;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.annotations.InCrossTld;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
|
@ -88,7 +89,8 @@ import org.joda.time.Duration;
|
|||
@Entity
|
||||
@javax.persistence.Entity(name = "Tld")
|
||||
@InCrossTld
|
||||
public class Registry extends ImmutableObject implements Buildable, DatastoreAndSqlEntity {
|
||||
public class Registry extends ImmutableObject
|
||||
implements Buildable, DatastoreAndSqlEntity, UnsafeSerializable {
|
||||
|
||||
@Parent @Transient Key<EntityGroupRoot> parent = getCrossTldKey();
|
||||
|
||||
|
@ -308,7 +310,7 @@ public class Registry extends ImmutableObject implements Buildable, DatastoreAnd
|
|||
* <p>There must be at least one entry in this set.
|
||||
*
|
||||
* <p>All entries of this list must be valid keys for the map of {@code DnsWriter}s injected by
|
||||
* <code>@Inject Map<String, DnsWriter></code>
|
||||
* {@code @Inject Map<String, DnsWriter>}
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
Set<String> dnsWriters;
|
||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.model.transfer;
|
|||
|
||||
import google.registry.model.Buildable.GenericBuilder;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
|
@ -27,7 +28,7 @@ import org.joda.time.DateTime;
|
|||
/** Fields common to {@link TransferData} and {@link TransferResponse}. */
|
||||
@XmlTransient
|
||||
@MappedSuperclass
|
||||
public abstract class BaseTransferObject extends ImmutableObject {
|
||||
public abstract class BaseTransferObject extends ImmutableObject implements UnsafeSerializable {
|
||||
/**
|
||||
* The status of the current or last transfer. Can be null if never transferred. Note that we
|
||||
* leave IgnoreSave off this field so that we can ensure that TransferData loaded from Objectify
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableSortedMap;
|
|||
import google.registry.model.common.TimedTransitionProperty;
|
||||
import google.registry.model.common.TimedTransitionProperty.TimedTransition;
|
||||
import google.registry.persistence.converter.StringMapDescriptor.StringMap;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
@ -30,7 +31,8 @@ import org.joda.time.DateTime;
|
|||
* Base JPA converter for {@link TimedTransitionProperty} objects that are stored in a column with
|
||||
* data type of hstore in the database.
|
||||
*/
|
||||
public abstract class TimedTransitionPropertyConverterBase<K, V extends TimedTransition<K>>
|
||||
public abstract class TimedTransitionPropertyConverterBase<
|
||||
K extends Serializable, V extends TimedTransition<K>>
|
||||
implements AttributeConverter<TimedTransitionProperty<K, V>, StringMap> {
|
||||
|
||||
abstract Map.Entry<String, String> convertToDatabaseMapEntry(Map.Entry<DateTime, V> entry);
|
||||
|
|
|
@ -25,6 +25,7 @@ import static google.registry.testing.DatabaseHelper.loadByKey;
|
|||
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.SerializeUtils.serializeDeserialize;
|
||||
import static org.joda.money.CurrencyUnit.USD;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
@ -46,6 +47,7 @@ import google.registry.persistence.VKey;
|
|||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.util.DateTimeUtils;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
|
@ -195,6 +197,20 @@ public class BillingEventTest extends EntityTestCase {
|
|||
ofyTmOrDoNothing(() -> assertThat(tm().loadByEntity(modification)).isEqualTo(modification));
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializable() {
|
||||
BillingEvent persisted = loadByEntity(oneTime);
|
||||
assertThat(serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
persisted = loadByEntity(oneTimeSynthetic);
|
||||
assertThat(serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
persisted = loadByEntity(recurring);
|
||||
assertThat(serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
persisted = loadByEntity(cancellationOneTime);
|
||||
assertThat(serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
persisted = loadByEntity(cancellationRecurring);
|
||||
assertThat(serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testParenting() {
|
||||
// Note that these are all tested separately because BillingEvent is an abstract base class that
|
||||
|
|
|
@ -30,6 +30,8 @@ import google.registry.model.domain.DomainBase;
|
|||
import google.registry.model.tld.Registry;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
|
@ -46,6 +48,15 @@ public class CursorTest extends EntityTestCase {
|
|||
fakeClock.setTo(DateTime.parse("2010-10-17TZ"));
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializable() {
|
||||
final DateTime time = DateTime.parse("2012-07-12T03:30:00.000Z");
|
||||
tm().transact(() -> tm().put(Cursor.createGlobal(RECURRING_BILLING, time)));
|
||||
Cursor persisted =
|
||||
tm().transact(() -> tm().loadByKey(Cursor.createGlobalVKey(RECURRING_BILLING)));
|
||||
assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSuccess_persistScopedCursor() {
|
||||
createTld("tld");
|
||||
|
|
|
@ -48,6 +48,7 @@ import google.registry.testing.DualDatabaseTest;
|
|||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
/** Unit tests for {@link ContactResource}. */
|
||||
|
@ -174,6 +175,14 @@ public class ContactResourceTest extends EntityTestCase {
|
|||
.hasValue(contactResource);
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializable() {
|
||||
ContactResource persisted =
|
||||
loadByForeignKey(ContactResource.class, contactResource.getForeignKey(), fakeClock.nowUtc())
|
||||
.get();
|
||||
assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testIndexing() throws Exception {
|
||||
verifyDatastoreIndexing(
|
||||
|
|
|
@ -56,6 +56,7 @@ import google.registry.testing.AppEngineExtension;
|
|||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import java.util.Arrays;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
|
@ -354,6 +355,14 @@ public class DomainBaseSqlTest {
|
|||
});
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializable() {
|
||||
createTld("com");
|
||||
insertInDb(contact, contact2, domain, host);
|
||||
DomainBase persisted = jpaTm().transact(() -> jpaTm().loadByEntity(domain));
|
||||
assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testUpdates() {
|
||||
createTld("com");
|
||||
|
|
|
@ -41,6 +41,8 @@ import google.registry.model.reporting.HistoryEntry;
|
|||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
|
@ -93,6 +95,44 @@ public class AllocationTokenTest extends EntityTestCase {
|
|||
assertThat(loadByEntity(singleUseToken)).isEqualTo(singleUseToken);
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializable() {
|
||||
AllocationToken unlimitedUseToken =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123Unlimited")
|
||||
.setTokenType(UNLIMITED_USE)
|
||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.setAllowedTlds(ImmutableSet.of("dev", "app"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar, NewRegistrar"))
|
||||
.setDiscountFraction(0.5)
|
||||
.setDiscountPremiums(true)
|
||||
.setDiscountYears(3)
|
||||
.setTokenStatusTransitions(
|
||||
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||
.put(START_OF_TIME, NOT_STARTED)
|
||||
.put(DateTime.now(UTC), TokenStatus.VALID)
|
||||
.put(DateTime.now(UTC).plusWeeks(8), TokenStatus.ENDED)
|
||||
.build())
|
||||
.build());
|
||||
AllocationToken persisted = loadByEntity(unlimitedUseToken);
|
||||
assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
|
||||
DomainBase domain = persistActiveDomain("example.foo");
|
||||
Key<HistoryEntry> historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 1);
|
||||
AllocationToken singleUseToken =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123Single")
|
||||
.setRedemptionHistoryEntry(HistoryEntry.createVKey(historyEntryKey))
|
||||
.setDomainName("example.foo")
|
||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.setTokenType(SINGLE_USE)
|
||||
.build());
|
||||
persisted = loadByEntity(singleUseToken);
|
||||
assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testIndexing() throws Exception {
|
||||
DomainBase domain = persistActiveDomain("blahdomain.foo");
|
||||
|
|
|
@ -39,6 +39,7 @@ import google.registry.persistence.VKey;
|
|||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.util.SerializeUtils;
|
||||
|
||||
/** Tests for {@link ContactHistory}. */
|
||||
@DualDatabaseTest
|
||||
|
@ -64,6 +65,18 @@ public class ContactHistoryTest extends EntityTestCase {
|
|||
});
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializable() {
|
||||
ContactResource contact = newContactResourceWithRoid("contactId", "contact1");
|
||||
insertInDb(contact);
|
||||
ContactResource contactFromDb = loadByEntity(contact);
|
||||
ContactHistory contactHistory = createContactHistory(contactFromDb);
|
||||
insertInDb(contactHistory);
|
||||
ContactHistory fromDatabase =
|
||||
jpaTm().transact(() -> jpaTm().loadByKey(contactHistory.createVKey()));
|
||||
assertThat(SerializeUtils.serializeDeserialize(fromDatabase)).isEqualTo(fromDatabase);
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testLegacyPersistence_nullContactBase() {
|
||||
ContactResource contact = newContactResourceWithRoid("contactId", "contact1");
|
||||
|
|
|
@ -55,6 +55,7 @@ import google.registry.testing.DatabaseHelper;
|
|||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
@ -87,6 +88,16 @@ public class DomainHistoryTest extends EntityTestCase {
|
|||
});
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializable() {
|
||||
DomainBase domain = addGracePeriodForSql(createDomainWithContactsAndHosts());
|
||||
DomainHistory domainHistory = createDomainHistory(domain);
|
||||
insertInDb(domainHistory);
|
||||
DomainHistory fromDatabase =
|
||||
jpaTm().transact(() -> jpaTm().loadByKey(domainHistory.createVKey()));
|
||||
assertThat(SerializeUtils.serializeDeserialize(fromDatabase)).isEqualTo(fromDatabase);
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testLegacyPersistence_nullResource() {
|
||||
DomainBase domain = addGracePeriodForSql(createDomainWithContactsAndHosts());
|
||||
|
|
|
@ -36,6 +36,7 @@ import google.registry.persistence.VKey;
|
|||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.util.SerializeUtils;
|
||||
|
||||
/** Tests for {@link HostHistory}. */
|
||||
@DualDatabaseTest
|
||||
|
@ -61,6 +62,17 @@ public class HostHistoryTest extends EntityTestCase {
|
|||
});
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializable() {
|
||||
HostResource host = newHostResourceWithRoid("ns1.example.com", "host1");
|
||||
insertInDb(host);
|
||||
HostResource hostFromDb = loadByEntity(host);
|
||||
HostHistory hostHistory = createHostHistory(hostFromDb);
|
||||
insertInDb(hostHistory);
|
||||
HostHistory fromDatabase = jpaTm().transact(() -> jpaTm().loadByKey(hostHistory.createVKey()));
|
||||
assertThat(SerializeUtils.serializeDeserialize(fromDatabase)).isEqualTo(fromDatabase);
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testLegacyPersistence_nullHostBase() {
|
||||
HostResource host = newHostResourceWithRoid("ns1.example.com", "host1");
|
||||
|
|
|
@ -45,6 +45,8 @@ import google.registry.model.transfer.TransferStatus;
|
|||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
|
@ -111,6 +113,14 @@ class HostResourceTest extends EntityTestCase {
|
|||
.containsExactly(newHost);
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializable() {
|
||||
HostResource newHost = host.asBuilder().setRepoId("NEWHOST").build();
|
||||
tm().transact(() -> tm().insert(newHost));
|
||||
HostResource persisted = tm().transact(() -> tm().loadByEntity(newHost));
|
||||
assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testLoadingByForeignKey() {
|
||||
assertThat(loadByForeignKey(HostResource.class, host.getForeignKey(), fakeClock.nowUtc()))
|
||||
|
|
|
@ -36,6 +36,7 @@ import google.registry.testing.DualDatabaseTest;
|
|||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
/** Unit tests for {@link PollMessage}. */
|
||||
|
@ -118,6 +119,20 @@ public class PollMessageTest extends EntityTestCase {
|
|||
assertThat(tm().transact(() -> tm().loadByEntity(pollMessage))).isEqualTo(pollMessage);
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializableOneTime() {
|
||||
PollMessage.OneTime pollMessage =
|
||||
persistResource(
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setEventTime(fakeClock.nowUtc())
|
||||
.setMsg("Test poll message")
|
||||
.setParent(historyEntry)
|
||||
.build());
|
||||
PollMessage persisted = tm().transact(() -> tm().loadByEntity(pollMessage));
|
||||
assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testPersistenceAutorenew() {
|
||||
PollMessage.Autorenew pollMessage =
|
||||
|
@ -133,6 +148,22 @@ public class PollMessageTest extends EntityTestCase {
|
|||
assertThat(tm().transact(() -> tm().loadByEntity(pollMessage))).isEqualTo(pollMessage);
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializableAutorenew() {
|
||||
PollMessage.Autorenew pollMessage =
|
||||
persistResource(
|
||||
new PollMessage.Autorenew.Builder()
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setEventTime(fakeClock.nowUtc())
|
||||
.setMsg("Test poll message")
|
||||
.setParent(historyEntry)
|
||||
.setAutorenewEndTime(fakeClock.nowUtc().plusDays(365))
|
||||
.setTargetId("foobar.foo")
|
||||
.build());
|
||||
PollMessage persisted = tm().transact(() -> tm().loadByEntity(pollMessage));
|
||||
assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testIndexingAutorenew() throws Exception {
|
||||
PollMessage.Autorenew pollMessage =
|
||||
|
|
|
@ -45,7 +45,9 @@ import google.registry.model.tld.Registries;
|
|||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.util.CidrAddressBlock;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
|
@ -135,6 +137,12 @@ class RegistrarTest extends EntityTestCase {
|
|||
assertThat(tm().transact(() -> tm().loadByKey(registrar.createVKey()))).isEqualTo(registrar);
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializable() {
|
||||
Registrar persisted = tm().transact(() -> tm().loadByKey(registrar.createVKey()));
|
||||
assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testIndexing() throws Exception {
|
||||
verifyDatastoreIndexing(registrar, "registrarName", "ianaIdentifier");
|
||||
|
|
|
@ -47,6 +47,8 @@ import google.registry.testing.DatabaseHelper;
|
|||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Optional;
|
||||
import org.joda.money.Money;
|
||||
|
@ -87,6 +89,16 @@ public final class RegistryTest extends EntityTestCase {
|
|||
.isEqualTo(Registry.get("tld"));
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testSerializable() {
|
||||
ReservedList rl15 = persistReservedList("tld-reserved15", "potato,FULLY_BLOCKED");
|
||||
Registry registry = Registry.get("tld").asBuilder().setReservedLists(rl15).build();
|
||||
tm().transact(() -> tm().put(registry));
|
||||
Registry persisted =
|
||||
tm().transact(() -> tm().loadByKey(Registry.createVKey(registry.tldStrId)));
|
||||
assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testFailure_registryNotFound() {
|
||||
createTld("foo");
|
||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.schema.registrar;
|
|||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.registrar.RegistrarContact.Type.WHOIS;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.testing.DatabaseHelper.insertInDb;
|
||||
import static google.registry.testing.DatabaseHelper.loadByEntity;
|
||||
import static google.registry.testing.SqlHelper.saveRegistrar;
|
||||
|
@ -27,6 +28,7 @@ import google.registry.persistence.transaction.JpaTestExtensions;
|
|||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationWithCoverageExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -74,4 +76,11 @@ class RegistrarContactTest {
|
|||
insertInDb(testRegistrarPoc);
|
||||
assertThat(loadByEntity(testRegistrarPoc)).isEqualTo(testRegistrarPoc);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSerializable_succeeds() {
|
||||
insertInDb(testRegistrarPoc);
|
||||
RegistrarContact persisted = jpaTm().transact(() -> jpaTm().loadByEntity(testRegistrarPoc));
|
||||
assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,5 +65,10 @@ public final class SerializeUtils {
|
|||
}
|
||||
}
|
||||
|
||||
/** Serializes an object then deserializes it. This is typically used in tests. */
|
||||
public static Object serializeDeserialize(Object object) {
|
||||
return deserialize(Object.class, serialize(object));
|
||||
}
|
||||
|
||||
private SerializeUtils() {}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue