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

Xtext与Ace Web编辑器代码生成请求失败排查求助

问题描述

基于Xtext Web编辑器的Ace支持,我在前端调用代码生成服务时遭遇404错误,具体情况如下:

前端触发代码

参考文档中的「调用服务」逻辑,通过按钮点击触发生成:

var editor = xtext.createEditor();
$("#save-button").click(function() {
    // editor.xtextServices.saveResource();
    editor.xtextServices.generate();
});

后端生成器实现

基于默认Greeting语法编写了代码生成器:

// filename: <MyLovaelyDslName>Generator.xtend

class Phase0Generator extends AbstractGenerator {

    override void doGenerate(
        Resource resource,
        IFileSystemAccess2 fsa,
        IGeneratorContext context
    ) {
        fsa.generateFile('greetings.txt', 'People to greet: ' + 
            resource.allContents
                .filter(Greeting)
                .map[name]
                .join(', '))
    }
}

错误表现

浏览器发起的10次GET请求全部返回404:

GET http://localhost:8080/xtext-service/generate?resource=67e22793.veri&requiredStateId=-7ffffff4 404 (Not Found)

随后弹出错误提示:

Xtext service 'generate' failed: Xtext service request failed after 10 attempts.
xtext-ace.js:1114 Xtext service 'generate' failed: Not Found

目前语法高亮和自定义验证功能均正常工作。

已做的配置

按照文档要求创建了XtextServlet子类,重写doGet方法拦截请求,能正常处理非generate请求,但不知道如何对接generate的处理逻辑:

@WebServlet(name = "XtextServices", urlPatterns = "/xtext-service/*")
public class Phase0Servlet extends XtextServlet {
    public void init() throws ServletException { /* ... */ }
    public void destroy() { /* ... */ }

    @Override
    protected void doGet(
        HttpServletRequest req,
        HttpServletResponse response
    ) throws ServletException, IOException
    {
        var service = getService(req);
        var serviceType = /* ... */.getParameter("serviceType");
        if (serviceType.equals("generate")) { /* ... */ }
        else                                { /* ... */ }
    }
}
解决方案

问题出在你的Servlet没有正确实现generate请求的处理逻辑,需要对接Xtext的生成器服务,具体步骤如下:

  1. 初始化生成器相关服务
    在Servlet的init方法中,通过Xtext的依赖注入容器获取生成器、生成上下文工厂:

    private IGenerator generator;
    private IGeneratorContext.Factory contextFactory;
    
    @Override
    public void init() throws ServletException {
        super.init();
        Injector injector = getInjector(); // 从父类获取Xtext注入器
        generator = injector.getInstance(IGenerator.class);
        contextFactory = injector.getInstance(IGeneratorContext.Factory.class);
    }
    
  2. 实现generate请求处理逻辑
    在doGet的generate分支中,加载目标资源、执行生成并返回结果:

    private void handleGenerateRequest(HttpServletRequest req, HttpServletResponse response) throws IOException {
        String resourceId = req.getParameter("resource");
        // 这里需要实现资源加载逻辑,比如从内存缓存中获取编辑器对应的Resource实例
        Resource resource = loadResource(resourceId);
        
        if (resource == null) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "资源不存在");
            return;
        }
    
        // 使用内存文件系统访问器捕获生成的文件内容
        MemoryFileSystemAccess fsa = new MemoryFileSystemAccess();
        IGeneratorContext context = contextFactory.createContext();
    
        try {
            generator.doGenerate(resource, fsa, context);
            // 将生成的文件列表转为JSON返回给前端
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            new ObjectMapper().writeValue(response.getWriter(), fsa.getFiles());
        } catch (Exception e) {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "生成失败:" + e.getMessage());
        }
    }
    
    private Resource loadResource(String resourceId) {
        // 替换为你的资源加载逻辑,比如从编辑器的内存缓存中获取
        return YourResourceStore.getResource(resourceId);
    }
    
  3. 完整Servlet代码

    @WebServlet(name = "XtextServices", urlPatterns = "/xtext-service/*")
    public class Phase0Servlet extends XtextServlet {
        private IGenerator generator;
        private IGeneratorContext.Factory contextFactory;
    
        @Override
        public void init() throws ServletException {
            super.init();
            Injector injector = getInjector();
            generator = injector.getInstance(IGenerator.class);
            contextFactory = injector.getInstance(IGeneratorContext.Factory.class);
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
            String serviceType = req.getParameter("serviceType");
            if ("generate".equals(serviceType)) {
                handleGenerateRequest(req, response);
            } else {
                super.doGet(req, response);
            }
        }
    
        private void handleGenerateRequest(HttpServletRequest req, HttpServletResponse response) throws IOException {
            String resourceId = req.getParameter("resource");
            Resource resource = loadResource(resourceId);
            
            if (resource == null) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND, "资源不存在");
                return;
            }
    
            MemoryFileSystemAccess fsa = new MemoryFileSystemAccess();
            IGeneratorContext context = contextFactory.createContext();
    
            try {
                generator.doGenerate(resource, fsa, context);
                response.setContentType("application/json");
                response.setCharacterEncoding("UTF-8");
                new ObjectMapper().writeValue(response.getWriter(), fsa.getFiles());
            } catch (Exception e) {
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "生成失败:" + e.getMessage());
            }
        }
    
        private Resource loadResource(String resourceId) {
            // 替换为你的资源加载逻辑,比如从编辑器的内存缓存中获取
            return YourResourceStore.getResource(resourceId);
        }
    }
    
  4. 注意事项

    • 确保你的Phase0Generator已被Xtext的依赖注入容器正确注册,否则injector.getInstance(IGenerator.class)会返回null
    • 资源加载逻辑必须和Xtext Web编辑器的资源管理一致,确保能获取到当前编辑器中的最新内容
    • 前端可以通过editor.xtextServices.generate().then(result => { ... })处理返回的生成结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 17:14:50