why libreoffice sdk crash when simultaneosly and concurrently create documents through a webservice?

半世苍凉 提交于 2019-12-13 04:44:26

问题


i am running a webservice that replace text in a docx template and then convet it to pdf. i am using ubuntu 18.04 and glassfish server for its deployment when i made a single request for the service of converting everything is ok , but when i made a double request too fast like a double clicking issue or concurrent request, i got this exception:

com.sun.star.lang.DisposedException at com.sun.star.lib.uno.environments.remote.JobQueue.removeJob(JobQueue.java:201) . . aused by: java.io.IOException: EOF reached - socket,host=localhost,port=8100,localHost=localhost,localPort=58494,peerHost=localhost,peerPort=8100 at com.sun.star.lib.uno.bridges.java_remote.XConnectionInputStream_Adapter.read(XConnectionInputStream_Adapter.java:50)

i build the code guided by examples, i am a begginer in openoffice and LibreOffice , i saw the line of the exception was poiting to xDesktop.terminate(); , so i made an experiment and remove that statement , so now there is no raising of the exception , but as i mention i am a begginer so i am not sure what the xDesktop.terminate(); does and what is the consequences of removing it?

here is the code im running :

    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();
        }       
    }

So this webservice method is planned to serve documents to a LOT of users, so if i got petition at the same time or too consecutive it will raise the exception unless i remove the xDesktop.terminate(); but i dont know if it will have further consequences like overriding the memory or things like that. thanks in advance.


回答1:


The problem is that xDesktop.terminate() requests to shut down the underlying soffice process (the Java API is just a wrapper around it basically). You have two options:

  1. Either pre-start libreoffice yourself, so you don't need to spawn a new soffice process all the time, but can just connect to an existing one. This has the benefit that the performance will be great if you have a lot of small requests (no startup cost), but then your conversions are not too isolated (security concern) and in practice conversions won't happen in parallel. In this case you started the soffice process, so just don't call xDesktop.terminate().

  2. Or you start up each soffice process using a dedicated, unique UserInstallation directory (see libreoffice --help), and then xDesktop.terminate() won't be a problem, since one conversion is one soffice process.

DisposedException just means that you were talking to a soffice process using the remote UNO protocol and while your request was in progress, somebody else killed the soffice process.

You need to research how the Java API allows passing custom soffice parameters, but in the worst case you can do something like soffice "--accept=socket,host=localhost,port=9999;urp;StarOffice.ServiceManager" -env:UserInstallation=file:///tmp/test, where you need to make sure that 9999 and /tmp/test is unique if you do two conversions in parallel. (Again, see documentation, it's possible to use unix sockets instead of TCP ports if you find that better.)

So the bottom line: if you share the soffice process between multiple conversions, then don't terminate the xDesktop singleton, as that'll "crash" the other conversion process(es).



来源:https://stackoverflow.com/questions/55621825/why-libreoffice-sdk-crash-when-simultaneosly-and-concurrently-create-documents-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!