【问题标题】:XSL Stylesheet Path with Quartz Job带有 Quartz 作业的 XSL 样式表路径
【发布时间】:2021-07-01 13:23:57
【问题描述】:

我有一个将 XML 数据转换为基于 XSL 的报告的操作,该报告可以在网页上查看。用户调用的单独操作可用于将此报告转换为 PDF 并将其保存到某个位置。

我希望每天使用 Quartz Scheduler 来运行报告并将报告另存为 PDF。我已经确认 Quartz Scheduler 运行成功,但是当它尝试将数据转换为 PDF 报告时失败了。

public byte[] render(Action action, String location) throws Exception {

    // Transform the source XML to System.out.
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    try {

        // configure fopFactory as desired
        FopFactory fopFactory = FopFactory.newInstance();

        // configure foUserAgent as desired
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        // Create a transformer for the stylesheet.
        Templates templates = null;
        Transformer transformer;
        if (location != null) {
            templates = getTemplates(location);
            transformer = templates.newTransformer();
        } else {
            transformer = TransformerFactory.newInstance().newTransformer();
        }
        transformer.setURIResolver(getURIResolver());
        Object result = action;

        Source xmlSource = getDOMSourceForStack(result);

        // Construct fop with desired output format
        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);
        Result res = new SAXResult(fop.getDefaultHandler());
        transformer.transform(xmlSource, res);
        return out.toByteArray();

    } catch (Exception e) {
        throw e;
    } finally {
        out.close(); // ...and flush...
    }
}

protected Templates getTemplates(String path) throws TransformerException, IOException {
    
    if (path == null) {
        throw new TransformerException("Stylesheet path is null");
    }
    Templates templates = null;
    URL resource = ServletActionContext.getServletContext().getResource(path);

    if (resource == null) {
        throw new TransformerException("Stylesheet " + path + " not found in resources.");
    }
    TransformerFactory factory = TransformerFactory.newInstance();
    templates = factory.newTemplates(new StreamSource(resource.openStream()));

    return templates;
}

protected Source getDOMSourceForStack(Object value)
        throws IllegalAccessException, InstantiationException {
    return new DOMSource(getAdapterFactory().adaptDocument("result", value));
}

protected AdapterFactory getAdapterFactory() {
    if (adapterFactory == null) {
        adapterFactory = new AdapterFactory();
    }
    return adapterFactory;
}

protected void setAdapterFactory(AdapterFactory adapterFactory) {
    this.adapterFactory = adapterFactory;
}

protected URIResolver getURIResolver() {
         return new ServletURIResolver(
                 ServletActionContext.getServletContext());
     }
 }

action 参数是运行要转换的报告的操作,location 参数是格式化报告的 XSL 样式表的位置。此操作在用户调用时起作用,但是当 Quartz 尝试按计划调用它时,它会在

处抛出 NullPointerException 错误
    URL resource = ServletActionContext.getServletContext().getResource(path);

线。有没有办法让 Quartz 使用这个转换操作?

【问题讨论】:

    标签: java xslt quartz


    【解决方案1】:

    您的代码抛出 NPE,因为它是由 Quartz 在 Struts 操作之外执行的,因此 ServletActionContext.getServletContext() 返回 null。您需要找到一种不同的方式来获取ServletContext。最简单的方法是实现一个ServletContextListener,在调用contextInitialized 方法时将ServletContext 实例保存在私有静态字段中。然后在您的 Quartz 作业代码中,您将使用如下内容:

    MyServletContextListener.getServletContext().getResource(path);

    getServletContext 是一个静态方法,您需要将其添加到您的ServletContextListener 中,它只会返回保存的ServletContext 实例。

    您需要确保在调用 ServletContextListener's contextInitialized 方法后启动 Quartz。最简单的方法是从 contextInitialized 方法启动 Quartz。这确保当 Quartz 执行任何作业时,ServletContext 字段将被初始化,MyServletContextListener.getServletContext() 不会返回 null。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-17
      • 1970-01-01
      • 1970-01-01
      • 2014-04-23
      • 1970-01-01
      • 2013-04-16
      • 2017-08-18
      • 1970-01-01
      相关资源
      最近更新 更多