我有一个动作,可以将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尝试按计划调用它时,它会在
URL resource = ServletActionContext.getServletContext().getResource(path);线路。有没有一种方法可以让Quartz使用这个转换操作?
发布于 2021-04-08 01:30:27
您的代码抛出NPE,因为它是由Quartz在Struts操作之外执行的,因此ServletActionContext.getServletContext()返回null。您需要找到一种不同的方法来获取ServletContext。最简单的方法是实现一个在调用ServletContext实例的contextInitialized方法时将其保存在私有静态字段中的ServletContextListener。然后,在Quartz作业代码中,您将使用类似以下内容:
MyServletContextListener.getServletContext().getResource(path);
getServletContext是一个需要添加到ServletContextListener中的静态方法,它只返回保存的ServletContext实例。
您需要确保在调用ServletContextListener's contextInitialized方法之后启动Quartz。最简单的方法是从contextInitialized方法启动Quartz。这确保了当Quartz执行任何作业时,ServletContext字段将被初始化,并且MyServletContextListener.getServletContext()不会返回null。
https://stackoverflow.com/questions/66957143
复制相似问题