Skip to content

Migrate EPP XML generation from Soy to JAXB and emails to FreeMarker#3038

Open
CydeWeys wants to merge 1 commit into
google:masterfrom
CydeWeys:freemarker
Open

Migrate EPP XML generation from Soy to JAXB and emails to FreeMarker#3038
CydeWeys wants to merge 1 commit into
google:masterfrom
CydeWeys:freemarker

Conversation

@CydeWeys
Copy link
Copy Markdown
Member

@CydeWeys CydeWeys commented May 8, 2026

This CL eliminates the deprecated Closure Template (Soy) engine from the Nomulus codebase.

Key changes:

  • Migrated all EPP tool commands (CreateDomain, UpdateDomain, etc.) from Soy templates to type-safe JAXB models using EppInput.
  • Migrated Spec11 emails to Apache FreeMarker using a new TemplateRenderer utility.
  • Updated EppInput and related models to support all necessary extensions (Fee, SecDNS, Metadata, AllocationToken, etc.).
  • Refactored DsRecord to remove Soy dependencies.
  • Updated tool test data XML files to match JAXB output (standardizing headers, removing redundant lang="en" attributes, and using self-closing tags).
  • Removed Soy dependencies and associated Gradle tasks from the build system.
  • Consolidated EPP exception classes to improve code health and remove circular dependencies.

Verified with ./gradlew :core:test and specialized tool command tests.


This change is Reviewable

@CydeWeys CydeWeys force-pushed the freemarker branch 4 times, most recently from 1268bcc to d9d1130 Compare May 11, 2026 14:37
}

/** The inner add type on the update extension. */
public static class Add extends AddRemoveBase {
@XmlElement(name = "id"),
@XmlElement(name = "name") })
List<String> targetUniqueIds;
public class ResourceCheck extends ImmutableObject implements ResourceCommand {
@CydeWeys CydeWeys force-pushed the freemarker branch 3 times, most recently from dcec4a2 to 9258e15 Compare May 11, 2026 19:17
Comment thread dependencies.gradle Outdated
'com.google.template:soy:[2024-02-26,)',
'com.google.truth:truth:[1.1.2,)',
'com.googlecode.json-simple:json-simple:[1.1.1,)',
'org.freemarker:freemarker:2.3.32',
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't lock this to this specific revision. Use the open-ended [ ) syntax.

Comment thread README.md Outdated
and is written primarily in Java. It is the software that
[Google Registry](https://www.registry.google/) uses to operate TLDs such as .google,
.app, .how, .soy, and .みんな. It can run any number of TLDs in a single shared registry
.app, .how, and .みんな. It can run any number of TLDs in a single shared registry
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this change?

@CydeWeys CydeWeys force-pushed the freemarker branch 2 times, most recently from 5f0a007 to 0b20767 Compare May 12, 2026 01:49
@XmlRootElement
@XmlType(propOrder = {"targetId", "innerAdd", "innerRemove", "innerChange"})
public static class Update extends ResourceUpdate<Update.AddRemove, Domain.Builder, Update.Change>
public static class Update
@XmlRootElement
@XmlType(propOrder = {"targetId", "innerAdd", "innerRemove", "innerChange"})
public static class Update extends ResourceUpdate<Update.AddRemove, Host.Builder, Update.Change> {
public static class Update
@CydeWeys CydeWeys force-pushed the freemarker branch 3 times, most recently from a4a0fc1 to cd82ada Compare May 12, 2026 15:22

/** The inner change type on a contact update command. */
public static class AddRemove extends ResourceUpdate.AddRemove {}
public static class ContactAddRemove extends ResourceUpdate.AddRemove {
/** The inner change type on a domain update command. */
@XmlType(propOrder = {"nameserverHostNames", "foreignKeyedDesignatedContacts", "statusValues"})
public static class AddRemove extends ResourceUpdate.AddRemove {
public static class DomainAddRemove extends ResourceUpdate.AddRemove {
@XmlType(propOrder = { "inetAddresses", "statusValues" })
public static class AddRemove extends ResourceUpdate.AddRemove {
@XmlType(propOrder = {"inetAddresses", "statusValues"})
public static class HostAddRemove extends ResourceUpdate.AddRemove {
@CydeWeys CydeWeys requested a review from weiminyu May 12, 2026 19:45
- Replace deprecated Soy templates for EPP XML with JAXB models and a refined Fluent DSL.
- Migrate Spec11 and administrative emails to FreeMarker with HTML auto-escaping.
- Remove Soy compiler, Gradle tasks, and library dependencies.
- Address PR feedback regarding shadowing, version locking, and security warnings.
- Enhance tests with comprehensive XML equality assertions using Java 15 text blocks.
- Improve Javadocs and maintain strict temporal consistency using java.time.

FreeMarker replaces Soy for email templating, providing native HTML auto-escaping and allowing the removal of the complex 'soyToJava' compilation step from the build process. This significantly simplifies the build system and reduces maintenance overhead. For EPP XML, migrating to JAXB allows tool-generated commands to use the same model classes as the server-side EPP flows. This ensures that tool-generated XML is always schema-compliant and eliminates the risk of divergence between tool templates and actual server-side implementation. This unified approach provides compile-time type safety and improves developer ergonomics via a refined fluent DSL.

The base ImmutableObject class now provides a public clone() override that correctly resets the cached hashCode to null. This centralizes the custom cloning logic previously handled by a static helper and ensures that all subclasses—including the newly added JAXB models—satisfy CodeQL security requirements without needing redundant per-class overrides. The legacy static clone(T) helper has been updated to delegate to this instance method to maintain compatibility and architectural consistency.
Copy link
Copy Markdown
Collaborator

@weiminyu weiminyu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@weiminyu reviewed 58 files and made 1 comment.
Reviewable status: 58 of 104 files reviewed, 10 unresolved discussions (waiting on CydeWeys).


common/src/main/java/google/registry/util/TemplateRenderer.java line 57 at r5 (raw file):

   * @throws RuntimeException if the template cannot be found, parsed, or processed
   */
  public String render(String templatePath, ImmutableMap<String, Object> dataModel) {

If template variables and dataModel map keys do not match, missing or unused data keys, will the render throw an error?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants