diff --git a/core/src/main/java/google/registry/batch/ExpandRecurringBillingEventsAction.java b/core/src/main/java/google/registry/batch/ExpandRecurringBillingEventsAction.java index 27efd9a0b..042b89cf4 100644 --- a/core/src/main/java/google/registry/batch/ExpandRecurringBillingEventsAction.java +++ b/core/src/main/java/google/registry/batch/ExpandRecurringBillingEventsAction.java @@ -44,6 +44,7 @@ import com.google.common.collect.Range; import com.google.common.collect.Streams; import com.google.common.flogger.FluentLogger; import google.registry.config.RegistryConfig.Config; +import google.registry.flows.domain.DomainPricingLogic; import google.registry.mapreduce.MapreduceRunner; import google.registry.mapreduce.inputs.NullInput; import google.registry.model.ImmutableObject; @@ -98,6 +99,8 @@ public class ExpandRecurringBillingEventsAction implements Runnable { @Inject @Parameter(PARAM_DRY_RUN) boolean isDryRun; @Inject @Parameter(PARAM_CURSOR_TIME) Optional cursorTimeParam; + + @Inject DomainPricingLogic domainPricingLogic; @Inject Response response; @Inject ExpandRecurringBillingEventsAction() {} diff --git a/core/src/main/java/google/registry/flows/custom/BaseFlowCustomLogic.java b/core/src/main/java/google/registry/flows/custom/BaseFlowCustomLogic.java index 6d8d34b4a..8c828693e 100644 --- a/core/src/main/java/google/registry/flows/custom/BaseFlowCustomLogic.java +++ b/core/src/main/java/google/registry/flows/custom/BaseFlowCustomLogic.java @@ -17,6 +17,8 @@ package google.registry.flows.custom; import google.registry.flows.FlowMetadata; import google.registry.flows.SessionMetadata; import google.registry.model.eppinput.EppInput; +import java.util.Optional; +import javax.annotation.Nullable; /** * An abstract base class for all flow custom logic that stores the flow's {@link EppInput} and @@ -24,26 +26,38 @@ import google.registry.model.eppinput.EppInput; */ public abstract class BaseFlowCustomLogic { - private final EppInput eppInput; - private final SessionMetadata sessionMetadata; - private final FlowMetadata flowMetadata; + @Nullable private final EppInput eppInput; + @Nullable private final SessionMetadata sessionMetadata; + @Nullable private final FlowMetadata flowMetadata; + /** + * Constructs a BaseFlowCustomLogic for the specified EPP flow state. + * + *

Note that it is possible for the EPP flow state to be absent, which happens when the custom + * logic is running outside the context of an EPP flow (e.g. {@link DomainPricingCustomLogic} in + * backend actions). + */ protected BaseFlowCustomLogic( - EppInput eppInput, SessionMetadata sessionMetadata, FlowMetadata flowMetadata) { + @Nullable EppInput eppInput, + @Nullable SessionMetadata sessionMetadata, + @Nullable FlowMetadata flowMetadata) { this.eppInput = eppInput; this.sessionMetadata = sessionMetadata; this.flowMetadata = flowMetadata; } - protected EppInput getEppInput() { - return eppInput; + /** Returns the {@link EppInput}, which may be empty outside a flow context. */ + protected Optional getEppInput() { + return Optional.ofNullable(eppInput); } - protected SessionMetadata getSessionMetadata() { - return sessionMetadata; + /** Returns the {@link SessionMetadata}, which may be empty outside a flow context. */ + protected Optional getSessionMetadata() { + return Optional.ofNullable(sessionMetadata); } - protected FlowMetadata getFlowMetadata() { - return flowMetadata; + /** Returns the {@link FlowMetadata}, which may be empty outside a flow context. */ + protected Optional getFlowMetadata() { + return Optional.ofNullable(flowMetadata); } } diff --git a/core/src/main/java/google/registry/flows/custom/CustomLogicFactory.java b/core/src/main/java/google/registry/flows/custom/CustomLogicFactory.java index 8bae8b0d1..270cdd810 100644 --- a/core/src/main/java/google/registry/flows/custom/CustomLogicFactory.java +++ b/core/src/main/java/google/registry/flows/custom/CustomLogicFactory.java @@ -18,6 +18,7 @@ import google.registry.config.RegistryConfig.ConfigModule; import google.registry.flows.FlowMetadata; import google.registry.flows.SessionMetadata; import google.registry.model.eppinput.EppInput; +import java.util.Optional; /** * A no-op base custom logic factory. @@ -63,7 +64,10 @@ public class CustomLogicFactory { } public DomainPricingCustomLogic forDomainPricing( - EppInput eppInput, SessionMetadata sessionMetadata, FlowMetadata flowMetadata) { - return new DomainPricingCustomLogic(eppInput, sessionMetadata, flowMetadata); + Optional eppInput, + Optional sessionMetadata, + Optional flowMetadata) { + return new DomainPricingCustomLogic( + eppInput.orElse(null), sessionMetadata.orElse(null), flowMetadata.orElse(null)); } } diff --git a/core/src/main/java/google/registry/flows/custom/CustomLogicModule.java b/core/src/main/java/google/registry/flows/custom/CustomLogicModule.java index 001ab8c8e..e9c294670 100644 --- a/core/src/main/java/google/registry/flows/custom/CustomLogicModule.java +++ b/core/src/main/java/google/registry/flows/custom/CustomLogicModule.java @@ -14,15 +14,17 @@ package google.registry.flows.custom; +import dagger.BindsOptionalOf; import dagger.Module; import dagger.Provides; import google.registry.flows.FlowMetadata; import google.registry.flows.SessionMetadata; import google.registry.model.eppinput.EppInput; +import java.util.Optional; /** Dagger module to provide instances of custom logic classes for EPP flows. */ @Module -public class CustomLogicModule { +public abstract class CustomLogicModule { @Provides static DomainCreateFlowCustomLogic provideDomainCreateFlowCustomLogic( @@ -81,9 +83,20 @@ public class CustomLogicModule { @Provides static DomainPricingCustomLogic provideDomainPricingCustomLogic( CustomLogicFactory factory, - EppInput eppInput, - SessionMetadata sessionMetadata, - FlowMetadata flowMetadata) { + Optional eppInput, + Optional sessionMetadata, + Optional flowMetadata) { + // Note that, for DomainPricingCustomLogic, the EPP flow state won't be present outside the + // context of an EPP flow. return factory.forDomainPricing(eppInput, sessionMetadata, flowMetadata); } + + @BindsOptionalOf + abstract EppInput optionalEppInput(); + + @BindsOptionalOf + abstract SessionMetadata optionalSessionMetadata(); + + @BindsOptionalOf + abstract FlowMetadata optionalFlowMetadata(); } diff --git a/core/src/main/java/google/registry/flows/custom/DomainPricingCustomLogic.java b/core/src/main/java/google/registry/flows/custom/DomainPricingCustomLogic.java index ef8e786af..c80bf1b1f 100644 --- a/core/src/main/java/google/registry/flows/custom/DomainPricingCustomLogic.java +++ b/core/src/main/java/google/registry/flows/custom/DomainPricingCustomLogic.java @@ -24,6 +24,7 @@ import google.registry.flows.domain.FeesAndCredits; import google.registry.model.ImmutableObject; import google.registry.model.eppinput.EppInput; import google.registry.model.tld.Registry; +import javax.annotation.Nullable; import org.joda.time.DateTime; /** @@ -34,7 +35,9 @@ import org.joda.time.DateTime; public class DomainPricingCustomLogic extends BaseFlowCustomLogic { public DomainPricingCustomLogic( - EppInput eppInput, SessionMetadata sessionMetadata, FlowMetadata flowMetadata) { + @Nullable EppInput eppInput, + @Nullable SessionMetadata sessionMetadata, + @Nullable FlowMetadata flowMetadata) { super(eppInput, sessionMetadata, flowMetadata); } diff --git a/core/src/main/java/google/registry/flows/domain/DomainPricingLogic.java b/core/src/main/java/google/registry/flows/domain/DomainPricingLogic.java index 3867c2a5e..a953aacce 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainPricingLogic.java +++ b/core/src/main/java/google/registry/flows/domain/DomainPricingLogic.java @@ -23,7 +23,6 @@ import static google.registry.util.PreconditionsUtils.checkArgumentPresent; import com.google.common.net.InternetDomainName; import google.registry.flows.EppException; import google.registry.flows.EppException.CommandUseErrorException; -import google.registry.flows.FlowScope; import google.registry.flows.custom.DomainPricingCustomLogic; import google.registry.flows.custom.DomainPricingCustomLogic.CreatePriceParameters; import google.registry.flows.custom.DomainPricingCustomLogic.RenewPriceParameters; @@ -50,7 +49,6 @@ import org.joda.time.DateTime; * providing a {@link DomainPricingCustomLogic} implementation that operates on cross-TLD or per-TLD * logic. */ -@FlowScope public final class DomainPricingLogic { @Inject DomainPricingCustomLogic customLogic; diff --git a/core/src/main/java/google/registry/module/backend/BackendRequestComponent.java b/core/src/main/java/google/registry/module/backend/BackendRequestComponent.java index ce9822a1c..fb06d0360 100644 --- a/core/src/main/java/google/registry/module/backend/BackendRequestComponent.java +++ b/core/src/main/java/google/registry/module/backend/BackendRequestComponent.java @@ -61,6 +61,7 @@ import google.registry.export.UploadDatastoreBackupAction; import google.registry.export.sheet.SheetModule; import google.registry.export.sheet.SyncRegistrarsSheetAction; import google.registry.flows.FlowComponent; +import google.registry.flows.custom.CustomLogicModule; import google.registry.mapreduce.MapreduceModule; import google.registry.model.replay.ReplicateToDatastoreAction; import google.registry.monitoring.whitebox.WhiteboxModule; @@ -103,6 +104,7 @@ import google.registry.tools.javascrap.CreateSyntheticHistoryEntriesAction; BillingModule.class, CloudDnsWriterModule.class, CronModule.class, + CustomLogicModule.class, DnsCountQueryCoordinatorModule.class, DnsModule.class, DnsUpdateConfigModule.class, diff --git a/core/src/main/java/google/registry/module/tools/ToolsRequestComponent.java b/core/src/main/java/google/registry/module/tools/ToolsRequestComponent.java index e7e677ce2..26655ccfe 100644 --- a/core/src/main/java/google/registry/module/tools/ToolsRequestComponent.java +++ b/core/src/main/java/google/registry/module/tools/ToolsRequestComponent.java @@ -48,14 +48,14 @@ import google.registry.tools.server.VerifyOteAction; @RequestScope @Subcomponent( modules = { - BackupModule.class, - DnsModule.class, - EppToolModule.class, - LoadTestModule.class, - MapreduceModule.class, - RequestModule.class, - ToolsServerModule.class, - WhiteboxModule.class, + BackupModule.class, + DnsModule.class, + EppToolModule.class, + LoadTestModule.class, + MapreduceModule.class, + RequestModule.class, + ToolsServerModule.class, + WhiteboxModule.class, }) interface ToolsRequestComponent { CreateGroupsAction createGroupsAction(); diff --git a/core/src/test/java/google/registry/flows/custom/TestCustomLogicFactory.java b/core/src/test/java/google/registry/flows/custom/TestCustomLogicFactory.java index d741db300..6b1fb96ce 100644 --- a/core/src/test/java/google/registry/flows/custom/TestCustomLogicFactory.java +++ b/core/src/test/java/google/registry/flows/custom/TestCustomLogicFactory.java @@ -17,6 +17,7 @@ package google.registry.flows.custom; import google.registry.flows.FlowMetadata; import google.registry.flows.SessionMetadata; import google.registry.model.eppinput.EppInput; +import java.util.Optional; /** A custom logic factory for testing. */ public class TestCustomLogicFactory extends CustomLogicFactory { @@ -29,7 +30,10 @@ public class TestCustomLogicFactory extends CustomLogicFactory { @Override public DomainPricingCustomLogic forDomainPricing( - EppInput eppInput, SessionMetadata sessionMetadata, FlowMetadata flowMetadata) { - return new TestDomainPricingCustomLogic(eppInput, sessionMetadata, flowMetadata); + Optional eppInput, + Optional sessionMetadata, + Optional flowMetadata) { + return new TestDomainPricingCustomLogic( + eppInput.orElse(null), sessionMetadata.orElse(null), flowMetadata.orElse(null)); } } diff --git a/core/src/test/java/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java b/core/src/test/java/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java index e79fa0c58..b5b8ba07d 100644 --- a/core/src/test/java/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java +++ b/core/src/test/java/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java @@ -36,7 +36,7 @@ public class TestDomainCreateFlowCustomLogic extends DomainCreateFlowCustomLogic new PollMessage.OneTime.Builder() .setParent(parameters.historyEntry()) .setEventTime(tm().getTransactionTime()) - .setRegistrarId(getSessionMetadata().getRegistrarId()) + .setRegistrarId(getSessionMetadata().get().getRegistrarId()) .setMsg("Custom logic was triggered") .build(); return EntityChanges.newBuilder()