You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 17升级:SoyTofu迁移到SoySauce遇ijData识别异常求助

问题描述

应用从Java 8升级到Java 17,需将原基于SoyTofu的代码迁移为SoySauce(Google Closure Templates),目标是最小化代码改动,但迁移中遇到核心问题:注入数据(ijData)无法正常工作,单元测试抛出编译异常。

现有代码

Foobar类代码

import com.google.template.soy.SoyFileSet;
import com.google.template.soy.tofu.SoyTofu;

public class Foobar {
    ...
    private SoyTofu soyTemplates;
    ...
    @Override
    protected void startUp() throws Exception {
        ...
        String templatesProperty = "templates/mail.soy templates/mail-admin.soy";
        try {
            String[] templates = templatesProperty.split("\\s+");
            if (templates.length > 0) {
                SoyFileSet.Builder builder = SoyFileSet.builder();
                for (String t : templates) {
                    URL url = getUrl(t);
                    builder.add(url);
                }
                soyTemplates = builder.build().compileToTofu();
            }
        }
        ...
    }

    public Message compose(MailItem item) {
        ...
        Map<String, Object> ijData = new HashMap<String, Object>();
        ijData.put("supported", true);
        ijData.put("brand", "Accounts");

        String renderSubject = soyTemplates.newRenderer(item.subject).setData(item.data).setIjData(ijData).render();
        message.setSubject(renderSubject);

        String renderBody = soyTemplates.newRenderer(item.body).setData(item.data).setIjData(ijData).render();
        message.setContent(renderBody, MediaType.TEXT_HTML);
        ...
    }
}

Soy模板片段

/**
 * Account request submitted subject
 */
{template accountRequestSubmittedSubject}
{@param username : string}
{$ij.brand} account request: {$username}
{/template}

错误信息

Caused by: com.google.template.soy.error.SoyCompilationException: errors during Soy compilation
file:/target/test-classes/templates/mail-admin.soy:8: error: Unknown variable.
8: {$ij.brand} account request: {$requestorUsername}
    ~~~

已尝试创建独立SoySauce构建器、将SoyTofu构建器转为SoySauce等方式,但均未解决问题。愿意接受实时编译的性能损耗(仅2个模板)。


解决方案

1. 修正模板:显式声明注入参数(ij)

新版本Google Closure Templates要求必须显式声明注入参数,不能隐式使用$ij。这是编译报错的核心原因,需修改模板:

单模板声明示例

/**
 * Account request submitted subject
 */
{template accountRequestSubmittedSubject}
{@param username : string}
{@inject brand : string}
{@inject supported : boolean}
{$brand} account request: {$username}
{/template}

多模板共用注入参数(推荐)

如果多个模板用到相同的ij参数,可在命名空间级别统一声明,避免重复:

{namespace mail.templates}
{@inject brand : string}
{@inject supported : boolean}

/**
 * Account request submitted subject
 */
{template accountRequestSubmittedSubject}
{@param username : string}
{$brand} account request: {$username}
{/template}

2. 替换SoyTofu为SoySauce,调整代码逻辑

SoySauce的API与SoyTofu存在差异,需逐步替换:

步骤1:替换导入语句

// 移除原有导入
// import com.google.template.soy.tofu.SoyTofu;
// 添加SoySauce导入
import com.google.template.soy.SoySauce;

步骤2:修改类成员变量

// 原代码
// private SoyTofu soyTemplates;
// 修改后
private SoySauce soyTemplates;

步骤3:调整编译逻辑

将编译方法从compileToTofu()改为compileToSauce():

// 原代码
// soyTemplates = builder.build().compileToTofu();
// 修改后
soyTemplates = builder.build().compileToSauce();

步骤4:修改渲染代码

SoySauce使用renderTemplate()方法渲染,注入数据通过withIj()传递:

// 原代码
// String renderSubject = soyTemplates.newRenderer(item.subject).setData(item.data).setIjData(ijData).render();
// 修改后
String renderSubject = soyTemplates.renderTemplate(item.subject, item.data)
    .withIj(ijData)
    .render();

// 同理修改邮件正文渲染
String renderBody = soyTemplates.renderTemplate(item.body, item.data)
    .withIj(ijData)
    .render();

3. (可选)启用实时编译

若要使用实时编译(仅建议开发场景),可直接通过SoySauce.builder()加载模板,跳过提前编译步骤:

try {
    String[] templates = templatesProperty.split("\\s+");
    if (templates.length > 0) {
        SoySauce.Builder sauceBuilder = SoySauce.builder();
        for (String t : templates) {
            URL url = getUrl(t);
            sauceBuilder.add(url);
        }
        soyTemplates = sauceBuilder.build();
    }
}

内容的提问来源于stack exchange,提问作者commadelimited

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 04:32:52