为什么libreoffice sdk在同时通过Web服务同时创建文档时崩溃?

问题描述 投票:0回答:1

我正在运行一个web服务,用于替换docx模板中的文本,然后将其传送到pdf。我正在使用ubuntu 18.04和glassfish服务器进行部署时,我对转换所有内容的服务提出单一请求是可以的,但是当我发出双重请求太快,如双击问题或并发请求时,我得到了这个例外:

com.sun.star.lib.uno.environments.remote.JobQueue.removeJob(JobQueue.java:201)中的com.sun.star.lang.DisposedException。 。 aused by:java.io.IOException:到达EOF - socket,host = localhost,port = 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();
        }       
    }

因此,这个webservice方法计划向很多用户提供文档,所以如果我同时请求或连续请求,它将引发异常,除非我删除xDesktop.terminate();但我不知道它是否会产生进一步的后果,如重写内存或类似的东西。提前致谢。

java pdf pdf-generation reporting libreoffice
1个回答
1
投票

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

  1. 要么自己预启动libreoffice,所以你不需要一直生成一个新的soffice进程,但只能连接到现有的进程。这样做的好处是,如果您有很多小请求(没有启动成本),性能会很好,但是您的转换不会太孤立(安全问题),实际上转换不会并行发生。在这种情况下,您启动了soffice进程,因此不要调用xDesktop.terminate()。
  2. 或者您使用专用的唯一UserInstallation目录启动每个soffice进程(请参阅libreoffice --help),然后xDesktop.terminate()将不会成为问题,因为一个转换是一个soffice进程。

DisposedException只是意味着你正在使用远程UNO协议与一个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单例,因为这会“崩溃”其他转换进程。

© www.soinside.com 2019 - 2024. All rights reserved.