gpt4 book ai didi

java - 为什么当通过 Web 服务同时创建文档时 libreoffice sdk 会崩溃?

转载 作者:行者123 更新时间:2023-12-02 10:01:09 32 4
gpt4 key购买 nike

我正在运行一个网络服务,它替换 docx 模板中的文本,然后将其转换为 pdf。 我正在使用 ubuntu 18.04 和 glassfish 服务器进行部署 当我提出一个转换服务的请求时,一切都很好,但是 当我太快地发出双重请求(例如双击问题或并发请求)时,我得到了这个异常:

com.sun.star.lang.DisposeException 在 com.sun.star.lib.uno.environments.remote.JobQueue.removeJob(JobQueue.java:201)。。由以下人员引起:java.io.IOException:到达EOF - 套接字,主机= localhost,端口= 8100,localHost = localhost,localPort = 58494,peerHost = localhost,peerPort = 8100在 com.sun.star.lib.uno.bridges.java_remote.XConnectionInputStream_Adapter.read(XConnectionInputStream_Adapter.java:50)

我按照示例构建了代码,我是 openoffice 和 LibreOffice 的初学者,我看到异常行指向 xDesktop.terminate(); ,所以我做了一个实验并删除了该语句,所以现在没有引发异常,但正如我提到的,我是一个初学者,所以我不确定 xDesktop.terminate(); 是什么;会发生什么以及删除它会产生什么后果?

这是我正在运行的代码:

    public Response getFilePdf(Integer idqueja) {       
try {

// Initialise
String oooExeFolder = "/opt/libreoffice6.1/program";
XComponentContext xContext = BootstrapSocketConnector.bootstrap(oooExeFolder);
//XComponentContext xContext = Bootstrap.bootstrap();

XMultiComponentFactory xMCF = xContext.getServiceManager();

Object oDesktop = xMCF.createInstanceWithContext(
"com.sun.star.frame.Desktop", xContext);

XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(
XDesktop.class, oDesktop);

// Load the Document
String workingDir = "/home/somePath/";
String myTemplate = workingDir + "template.docx";

if (!new File(myTemplate).canRead()) {
throw new RuntimeException("Cannotix load template:" + new File(myTemplate));
}

XComponentLoader xCompLoader = (XComponentLoader) UnoRuntime
.queryInterface(com.sun.star.frame.XComponentLoader.class, xDesktop);

String sUrl = "file:///" + myTemplate;

PropertyValue[] propertyValues = new PropertyValue[0];

propertyValues = new PropertyValue[1];
propertyValues[0] = new PropertyValue();
propertyValues[0].Name = "Hidden";
propertyValues[0].Value = new Boolean(true);

XComponent xComp = xCompLoader.loadComponentFromURL(
sUrl, "_blank", 0, propertyValues);


// Manipulate
XReplaceDescriptor xReplaceDescr = null;
XReplaceable xReplaceable = null;

XTextDocument xTextDocument = (XTextDocument) UnoRuntime
.queryInterface(XTextDocument.class, xComp);

xReplaceable = (XReplaceable) UnoRuntime
.queryInterface(XReplaceable.class,
xTextDocument);

xReplaceDescr = (XReplaceDescriptor) xReplaceable
.createReplaceDescriptor();


xReplaceDescr.setSearchString("<version>");
xReplaceDescr.setReplaceString("1.x");
xReplaceable.replaceAll(xReplaceDescr);
// mail merge the date
xReplaceDescr.setSearchString("<number>");
xReplaceDescr.setReplaceString("12345677");
xReplaceable.replaceAll(xReplaceDescr);


OOoOutputStream output= new OOoOutputStream();

// save as a PDF
XStorable xStorable = (XStorable) UnoRuntime
.queryInterface(XStorable.class, xComp);

propertyValues = new PropertyValue[2];
// Setting the flag for overwriting
propertyValues[0] = new PropertyValue();
propertyValues[1] = new PropertyValue();

propertyValues[0].Name = "OutputStream";
propertyValues[0].Value = output;
// Setting the filter name

propertyValues[1].Name = "FilterName";
propertyValues[1].Value = "writer_pdf_Export";

// Appending the favoured extension to the origin document name
//String myResult = workingDir + "fileConverted.pdf";
xStorable.storeToURL("private:stream", propertyValues);


// shutdown
xDesktop.terminate();

ByteArrayInputStream inStream = new ByteArrayInputStream(output.toByteArray());



ResponseBuilder response = Response.ok((Object) inStream);
response.header("Content-Disposition", "attachment;filename=template.pdf");
return response.build();


} catch (Exception e) {
e.printStackTrace();
ResponseBuilder response = Response.serverError();
return response.build();
}
}

所以这个网络服务方法计划为很多用户提供文档,所以如果我同时收到请愿书或太连续,它将引发异常,除非我删除 xDesktop.terminate();但我不知道它是否会产生进一步的后果,例如覆盖内存或类似的事情。提前致谢。

最佳答案

问题在于 xDesktop.terminate() 请求关闭底层 soffice 进程(Java API 基本上只是它的包装器)。您有两个选择:

  1. 您可以自己预先启动 libreoffice,这样您就不需要一直生成新的 soffice 进程,而只需连接到现有的进程即可。这样做的好处是,如果您有很多小请求(无启动成本),性能会很好,但您的转换不会太孤立(安全问题),并且实际上转换不会并行发生。在本例中,您启动了 soffice 进程,因此不要调用 xDesktop.terminate()。

  2. 或者您使用专用的、唯一的 UserInstallation 目录启动每个 soffice 进程(请参阅 libreoffice --help),然后 xDesktop.terminate() 将不会出现问题,因为一次转换就是一个 soffice 进程。

DisposeException 只是意味着您正在使用远程 UNO 协议(protocol)与 soffice 进程进行通信,并且当您的请求正在进行时,其他人终止了 soffice 进程。

您需要研究 Java API 如何允许传递自定义 soffice 参数,但在最坏的情况下,您可以执行类似 soffice "--accept=socket,host=localhost,port=9999;urp;StarOffice 的操作。 ServiceManager"-env:UserInstallation=file:///tmp/test,如果并行执行两个转换,则需要确保 9999 和 /tmp/test 是唯一的。 (再次,请参阅文档,如果您发现更好的话,可以使用 unix 套接字而不是 TCP 端口。)

底线是:如果您在多个转换之间共享 soffice 进程,则不要终止 xDesktop 单例,因为这会导致其他转换进程“崩溃”。

关于java - 为什么当通过 Web 服务同时创建文档时 libreoffice sdk 会崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55621825/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com