Apache OpenOffice (AOO) Bugzilla – Issue 63270
Problem with closing a document with API & JAVA
Last modified: 2018-09-23 16:44:45 UTC
Hi, i would to close a document that i have generated withe the API (the document is a Writer, that i have composed with some rtf files with images and table and then is converted in sxw). I use the code that i have found in the SDK the code is this: /** * Try to close the document without any saving of modifications. * We can try it only! Controller and/or model of this document * can disagree with that. But mostly they doesn't do so. * * @param xDocument document which should be clcosed */ public static void closeDocument(com.sun.star.lang.XComponent xDocument) { try { // Check supported functionality of the document (model or controller). com.sun.star.frame.XModel xModel = (com.sun.star.frame.XModel)UnoRuntime.queryInterface( com.sun.star.frame.XModel.class, xDocument); if(xModel!=null) { // It's a full featured office document. // Reset the modify state of it and close it. // Note: Model can disgree by throwing a veto exception. com.sun.star.util.XModifiable xModify = (com.sun.star.util.XModifiable)UnoRuntime.queryInterface( com.sun.star.util.XModifiable.class, xModel); xModify.setModified(false); xDocument.dispose(); } else { // It's a document which supports a controller .. or may by a pure // window only. If it's at least a controller - we can try to // suspend him. But - he can disagree with that! com.sun.star.frame.XController xController = (com.sun.star.frame.XController)UnoRuntime.queryInterface( com.sun.star.frame.XController.class, xDocument); if(xController!=null) { if(xController.suspend(true)==true) { // Note: Don't dispose the controller - destroy the frame // to make it right! com.sun.star.frame.XFrame xFrame = xController.getFrame(); xFrame.dispose(); } } } } catch(com.sun.star.beans.PropertyVetoException exVeto) { // Can be thrown by "setModified()" call on model. // He disagree with our request. // But there is nothing to do then. Following "dispose()" call wasn't // never called (because we catch it before). Closing failed -that's it. exVeto.printStackTrace(); } catch(com.sun.star.lang.DisposedException exDisposed) { // If an UNO object was already disposed before - he throw this special // runtime exception. Of course every UNO call must be look for that - // but it's a question of error handling. // For demonstration this exception is handled here. exDisposed.printStackTrace(); } catch(com.sun.star.uno.RuntimeException exRuntime) { // Every uno call can throw that. // Do nothing - closing failed - that's it. exRuntime.printStackTrace(); } } But sometimes and underline sometimes, the API stops before the istruction "xDocument.dispose()".. I don't have any error... if i kill the soffice process, i obtain this error: com.sun.star.lang.DisposedException: com.sun.star.io.IOException: EOF reached - socket,host=localhost,port=10100,localHost=localhost,localPort=60088,peerHost=localhost,peerPort=10100 at com.sun.star.lib.uno.bridges.java_remote.java_remote_bridge$MessageDispatcher.invoke(java_remote_bridge.java:282) at com.sun.star.lib.uno.bridges.java_remote.java_remote_bridge$MessageDispatcher.run(java_remote_bridge.java:175) I try with OOo 2.0.1, with OOo 1.1.4 but the error is the same..
sw->thoriredd: the fact that xModifiable.setModified(false) doesn't return lets me thinks that the office isn't properly working at this stage anymore, maybe because of something that has been done beforehand. Generally I would avoid to use "xComponent.dispose" to close the document and instead query xCloseable from your xModel and use the method "xCloseable.close(true)" instead. This way the possibility of a CloseVetoException is given in case the document can't be closed for whatever reason. Could you check if changing your code this way avoids the "freeze" of your program ?
I try to us XCloseable com.sun.star.util.XCloseable xClose=(com.sun.star.util.XCloseable)UnoRuntime.queryInterface( com.sun.star.util.XCloseable.class,xModel); xClose.close(true); instead of xComponent.dispose(); but the problem remain.. The very strange thing is that the first time that i run the application after the start of OO, all is ok, then at the second or third,ecc...(it is random) i can obtain 2 different situations: I don't obtain any error and the process remains suspend.., or the process goes down with a DisposedException..
Sometimes openoffice crash and obtain this error_log that i have attached
Created attachment 34959 [details] Error Log of OO crash
sw->thoriredd: The log you send only tells me that your OOo1.1.4 crashed somewhere in writer ;-) ... to understand the scenario a wee bit better could you elaborate what exactly you are doing ? ... does your program load a document, manupilate it and then closes it again ? ... If so does it happen with a special document are with every you used so far ? ... If it is only one document does the office survive loading it via UI ? ... If the UI manages to load it, do you load it hidden when using the API and how is the office started "headless" ? ... questions over questions :-) ... And one final one ... does the problem still appear with OOo2.0.2 ?
I try to explain better what my macro does: First of all it loads a blank document and creates headers,footers and sections. Then it imports about 20 rtf files and before everyone it creates a table with 4 column and 1 row. Then the macro inserts about 2-5 images (anchored at paragraph or as character) Finally, the macro replaces some string in the document, and then save and close the document. However the document is generated correctly even though the error. The soffice process is started before the macro run, with the parameter -headless and -minimize; during the execution of the macro, the document appear on the display. I have the same error also with OOo2.0.2. With this changes to the code: ... // xModify.setModified(false); com.sun.star.util.XCloseable xCloseM=(com.sun.star.util.XCloseable)UnoRuntime.queryInterface( com.sun.star.util.XCloseable.class,xModel); com.sun.star.util.XCloseable xCloseC=(com.sun.star.util.XCloseable)UnoRuntime.queryInterface( com.sun.star.util.XCloseable.class,xComponent); try { xCloseM.close(true); xCloseC.close(true); } catch (com.sun.star.util.CloseVetoException exCloseVeto) { exCloseVeto.printStackTrace(); } ... I obtain a DisposeException and that, in case of error, the office goes down, but don't crash..
sw->thoriredd: quite a lot of things your program does :-) ... briefly to the changed code ... no reason to get XCloseable twice this way you will always get a DisposedException in the line with the second "close" call since the object is already disposed at this point. The original issue stated that you freeze when calling "xModifiable.setModified(false)" ... since you commented that out does it now freeze within the first "xCloseable.close(true)" ?
With or without the code xModifiable.setModified(false) i obtain the same error.. I have commented this line because i save the document before in the code. I cancel the second xCloseable.close(true) but the result doesn't change.. and i obtain always the DisposedException when OpenOffice goes down..
sw->thoriredd: I try to understand the behaviour ... maybe my brain doesn't work properly at the moment ;-) ... originally you had xModifiable.setModified(false); xComponent.dispose(); and sometimes your program stopped at the first call and you had to kill the office manually which will no doubt raise a DisposedException in the dispose() call because the office is gone. Now you only have xCloseable.close(true) what happens now ... does it sometimes freeze in this call and you have to kill the office manually followed by the DisposedException ... or do you always get a DisposedException when calling close(true) now ?
I try to be more clear now: The program doesn't stop at the first call, but at the second or third or fourth call. I don't kill the office manually, when the execution of the macro is on the line-code xCloseable.close(true) it remains some second, and then it goes down! and when this happened, i have the DisposedException return on the Apache log... The only change between the first and the second version of my code, is that don't happened that office freeze and display the window of "Send Error"... I hope that now the situation is more clear..
I don't know if it is a good thing, but now, i obtain the same error also on the first call :-) , the code that i use to save and close now is this: XStorable xstorable=(XStorable)UnoRuntime.queryInterface(XStorable.class,xComponent); PropertyValue[] storeProps=new PropertyValue[0]; xstorable.storeAsURL(url+".sxw",storeProps); //System.gc(); xstorable.store(); XModel xModel=(XModel)UnoRuntime.queryInterface(XModel.class,xComponent); if(xModel!=null) { com.sun.star.util.XModifiable xModify = (com.sun.star.util.XModifiable)UnoRuntime.queryInterface( com.sun.star.util.XModifiable.class, xModel); xModify.setModified(false); com.sun.star.util.XCloseable xClose=(com.sun.star.util.XCloseable)UnoRuntime.queryInterface( com.sun.star.util.XCloseable.class,xComponent); xClose.close(true); } else { com.sun.star.frame.XController xController = (com.sun.star.frame.XController)UnoRuntime.queryInterface( com.sun.star.frame.XController.class, xComponent); if(xController!=null) { if(xController.suspend(true)==true) com.sun.star.frame.XFrame xFrame = xController.getFrame(); xFrame.dispose(); } } } } catch (com.sun.star.io.IOException exIO) { System.out.println("ECC2"); exIO.printStackTrace(System.out); } catch(com.sun.star.lang.DisposedException exDisposed) { System.out.println("ECC3"); exDisposed.printStackTrace(); } catch(com.sun.star.uno.RuntimeException exRuntime) { System.out.println("ECC4"); exRuntime.printStackTrace(); } catch (Exception e ) { System.out.println("ECC5"); e.printStackTrace(System.out); } The error is the same, in the line xClose.close(true) office wait 2-3 second, then goes down, and return the DisposedException...
sw->thoriredd: reproducible is good, that it happens at all not so good ;-) When xCloseable.close() throws a DisposedException there are good chances that the document you want to close or the office at all isn't there anymore. There are two things I'd like you to do ... firstly open an arbitrary empty document which you keep open to ensure that your "headless" office doesn't shut down after the last document was closed ... if this doesn't help please secondly strip your program down and attach the essentiels to this issue so that I can reproduce it two ... hopefully we so can figure out which part of the things you do in your program causes the problems.
Ok, i think that i have found where is the problem: xCloseable.close() crash only when i try to insert an image in the footer.. This is the method that i use: protected void numeriDiPagina(boolean immaginefooter,CodiceStruct[] codici,String percorso_img) { int i=0,j=0,count=0; String urllogo_array[]=null; String style_array[]=null; String tagcomandi=null; String comandi[]=null; String temp_url=null; int lunghezza=0; int r=0; String riduzione=null; String subtagcomandi=null; Integer alt,lar; int newalt=0,newlar=0; try { //Vengono contante quante sezioni(keyform) ci sono nell'elenco dei codici for (i=0;i<codici.length;i++) if (codici[i].ultimocodice) count++; urllogo_array=new String[count]; style_array=new String[count]; //Estraggo i valori di urllogo per i page_style tranne l'ultimo for (i=0;i<codici.length;i++) { if (codici[i].keyform_succ!=null) { urllogo_array[j]=codici[i].urllogo; if (j<(count-1)) style_array[j+1]=codici[i].keyform_succ; j=j+1; } } //Assegno l'ultimo urllogo che non viene preso dal ciclo precedente perchè keyform_succ è nullo urllogo_array[count-1]=codici[codici.length-1].urllogo; //Assegno il primo stile style_array[0]="Standard"; for (i=0;i<count;i++) { //Richiedo l'interfaccia per accedere agli stili XStyleFamiliesSupplier StyleFam = (XStyleFamiliesSupplier) UnoRuntime.queryInterface(XStyleFamiliesSupplier.class, xTextDocument); //Tramite l'interfaccia di accesso by Name, richiedo gli stili della pagina XNameAccess StyleFamNames = StyleFam.getStyleFamilies(); XNameAccess PageStyles = (XNameAccess) UnoRuntime.queryInterface(XNameAccess.class,StyleFamNames.getByName("PageStyles")); XStyle xStyle = (XStyle) UnoRuntime.queryInterface(XStyle.class,PageStyles.getByName(style_array[i])); XPropertySet xPropertySetStyle = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, xStyle); //Attivo i footer xPropertySetStyle.setPropertyValue("FooterIsOn", "TRUE"); //Imposta la distanza del FOOTER dal corpo della pagina if ( (immaginefooter) && (urllogo_array[i]!=null)) { xPropertySetStyle.setPropertyValue("FooterBodyDistance",new Integer(100)); //Per inserire l'immagine nel footer più a destra rispetto alla linea dei codici //Ricordarsi di cambiare anche la posizione del TABSTOP xPropertySetStyle.setPropertyValue("FooterRightMargin",new Integer(-1000)); } else xPropertySetStyle.setPropertyValue("FooterBodyDistance",new Integer(1000)); //Richiedo l'interfaccia per scrivere nel footer XText xTextfooter = (XText) UnoRuntime.queryInterface(XText.class, xPropertySetStyle.getPropertyValue("FooterText")); TextCursor = xTextfooter.createTextCursor(); //Imposto le proprietà di scrittura (allineamento,colore e dimensione) XPropertySet xCursorProps=(XPropertySet) UnoRuntime.queryInterface(XPropertySet.class,TextCursor); xCursorProps.setPropertyValue("ParaAdjust",com.sun.star.style.ParagraphAdjust.CENTER); xCursorProps.setPropertyValue("CharColor",new Integer(0x000000)); xCursorProps.setPropertyValue("CharHeight",new Float(10.0)); if ((immaginefooter) && (urllogo_array[i]!=null)) { TabStop tb[]=new TabStop[2]; tb[0]=new TabStop(); tb[0].Alignment=com.sun.star.style.TabAlign.CENTER; tb[1]=new TabStop(); tb[1].Alignment=com.sun.star.style.TabAlign.RIGHT; tb[0].Position=8750; tb[1].Position=18500; //All'inizio era 17500 xCursorProps.setPropertyValue("ParaTabStops",tb); } //Richiedo l'interfaccia per accedere alla Factory di creazione di "ogggetti" per il documento mxDocFactory = (XMultiServiceFactory) UnoRuntime.queryInterface( XMultiServiceFactory.class, xTextDocument); //Creo l'istanza per i numeri di pagina Object pn=mxDocFactory.createInstance("com.sun.star.text.TextField.PageNumber"); //Richiedo l'interfaccia TextField(per il numero) e quella delle proprietà del TextField XTextField xTextField = (XTextField) UnoRuntime.queryInterface(XTextField.class,pn); XPropertySet xPropertySetTextField = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class,xTextField); //Imposto le proprietà del numero xPropertySetTextField.setPropertyValue("NumberingType",new Short(NumberingType.ARABIC)); xPropertySetTextField.setPropertyValue("SubType",com.sun.star.text.PageNumberType.CURRENT ); if ((immaginefooter) && (urllogo_array[i]!=null)) { xTextfooter.insertString(TextCursor,"\t",false); xTextfooter.insertTextContent(TextCursor, xTextField, false); xTextfooter.insertString(TextCursor,"\t",false); //xTextfooter.insertString(TextCursor,"IMM",false); //Ottengo il TextRange in cui è contenuta la stringa //Richiedo l'interfaccia della Factory per creare un'istanza di un'oggetto grafico mxDocFactory =(XMultiServiceFactory)UnoRuntime.queryInterface(XMultiServiceFactory.class, xTextDocument); Object gObject = mxDocFactory.createInstance("com.sun.star.text.GraphicObject" ); XTextContent gContent=(XTextContent)UnoRuntime.queryInterface(XTextContent.class, gObject); XNamed xGOName = (XNamed)UnoRuntime.queryInterface(XNamed.class, gObject); //AGGIUNTA String nomeimmagine="ImmagineF"; xGOName.setName(nomeimmagine); //AGGIUNTA //Richiedo l'interfaccia per accedere alle proprietà dell'oggetto XPropertySet ps = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, gObject); //Lo inserisco come ancorato ad un carattere ps.setPropertyValue( "AnchorType",TextContentAnchorType.AS_CHARACTER); //ps.setPropertyValue("AnchorType",TextContentAnchorType.AT_PARAGRAPH); //ps.setPropertyValue("SurroundAnchorOnly",new Boolean(true)); ps.setPropertyValue("GraphicURL",percorso_img+urllogo_array[i]); //Inserisco l'immagine xTextfooter.insertTextContent(TextCursor,gContent, false); XTextRange xtrgObject=gContent.getAnchor(); String newurl=new String(""); // Primo oggetto grafico temporaneo. Object jloShape1 = mxDocFactory.createInstance("com.sun.star.drawing.GraphicObjectShape"); XShape xGOShape1 = (XShape)UnoRuntime.queryInterface(XShape.class, jloShape1); XTextContent xTCShape1 = (XTextContent)UnoRuntime.queryInterface(XTextContent.class, xGOShape1); XPropertySet xPSShape1 = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xGOShape1); // Secondo oggetto grafico temporaneo. Object jloShape2 = mxDocFactory.createInstance("com.sun.star.drawing.GraphicObjectShape"); XShape xGOShape2 = (XShape)UnoRuntime.queryInterface(XShape.class, jloShape2); XTextContent xTCShape2 = (XTextContent)UnoRuntime.queryInterface(XTextContent.class, xGOShape2); XPropertySet xPSShape2 = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xGOShape2); // Il primo oggetto temporaneo, punta allo stesso url dell'immagine xPSShape1.setPropertyValue("GraphicURL",percorso_img+urllogo_array[i]); // Inserento il primo oggetto temporaneo, OpenOffice crea la sua Bitmap xtrgObject.getText().insertTextContent(xtrgObject, xTCShape1, false); // Assegna la Bitmap del primo oggetto grafico temporaneo al secondo oggetto grafico temporaneo xPSShape2.setPropertyValue("GraphicObjectFillBitmap", xPSShape1.getPropertyValue("GraphicObjectFillBitmap")); //Inserendo il secondo oggetto grafico temporaneo, OpenOffice crea il suo URL interno (e la sua bitmap) xtrgObject.getText().insertTextContent(xtrgObject, xTCShape2, false); // Ora si può eliminare il primo oggetto temporaneo xtrgObject.getText().removeTextContent(xTCShape1); // Estraggo l'URL interno dal secondo oggetto temporaneo newurl = xPSShape2.getPropertyValue("GraphicURL").toString(); // Ed ora lo assegnamo alla immagine ps.setPropertyValue("GraphicURL", newurl); // Ora si può eliminare anche il secondo oggetto temporaneo xtrgObject.getText().removeTextContent(xTCShape2); } else { //Inserisco il numero xTextfooter.insertTextContent(TextCursor, xTextField, false); } } } catch (Exception e) { e.printStackTrace(System.out); } } The first part of the method is used to count how many section(and so now many styles) will be in the final document, then i insert the number of the page in the center of the footer and with a \t i insert the image in the bottom-right corner of the page.. If i don't insert the image, all is ok... The very "fun" thing is that, if i run the program on a Window platform with my local open_office, there aren't any kind of problem..the method XClose.close() run correctly, and the office document close correctly (with the right image in the footer)
what does "newurl" contain when you do the remote run ... is it a valid url or null ?
newurl contain a string like this: vnd.sun.star.GraphicObject:1000000000000176000000BD1F52B828 I think this is the reference internal to the image...
sw->thoriredd: mmm that is really strange, since I don't have any problems inserting graphics with different urls wherever I want and then close and save the document ... so I thought maybe on the remote side (since you said it works locally) the string might be accidently NULL which would kill the java-bridge and with that the office ... doesn't seem to be that way ... can you provide a working sample to make the bahaviour reproducible ?
All the objects are correctly istantiate, in fact the image is insert correctly in the final document, the strings are not null. I found that the line that bring office to crash during the call of the metod xClose.close() is this: xCellText.insertTextContent(cellcursor,gContent, false); (There is another way to insert an image?? i don't think so...) It's difficult for me to make a working sample, because we extract the data from a database..
sw->thoriredd: mmmm ... none of the snippets you posted so far contains insertion of graphics in text tables, but a quick check showed that this also throws any exception when I try it ... to really get a clue what is going wrong I'll need a running sample that reproduces the behaviour.
In the zip there is an example: now i explain to you how use it: This is a web-application, so you must copy it in a webapps on Tomcat. Then you must change the file config.properties that is in WEB-INF/classes in this file you must modify this parameters: test.portaO the port where OpenOffice run (in headless and minimize mode) test.portaT the port of the Tomcat test.host = the host name of the server where you run the web-application test.server = the address on the file-system of the server test.percorso = Don't change this test.percorso_img= the address on the file-system of the server+path MacroWeb/FileMacro/Bitmaps/ Then you can try the macro with http://hostname:port/MacroWeb/prova.jsp and click on go to launch. If you want the sourcecode is in the path WEB-INF/src In the path WEB-INF/lib there are the OO 1.1.4 library (this in the OFFICE_HOME/program/classes) I hope that you can try this!!! The document that you will obtain is a simply version of the one that i generate in my application(without the files RTF), but with the image in the footer that bring xClose.close() to crash...
Created attachment 35087 [details] The zip with the Example Web-Application
Created attachment 35088 [details] The zip with the Example Web-Application
sw->thoriredd: after removing all references to the Oracle-jdbc calls and adding a nuovo.bmp I manage to make it run and indeed the office dies prematurely as soon as xCloseable.close() is called. sw->mba: the created document can't be closed until I completely shut down the web-server, even if I keep the document open in the java-code by commenting out "xCloseable.close()" and close the document via UI after the servlet returns and then close the document via UI the office dies without creating a crash report ... in the command line I see # # An unexpected error has been detected by HotSpot Virtual Machine: # # SIGSEGV (0xb) at pc=0x61399a48, pid=64014, tid=1 # # Java VM: Java HotSpot(TM) Client VM (1.5.0_04-b05 mixed mode) # Problematic frame: # C [libsw680ss.so+0x399a48] # # An error report file with more information is saved as /tmp/hs_err_pid64014.log # # If you would like to submit a bug report, please visit: # http://java.sun.com/webapps/bugreport/crash.jsp # [error occurred during error reporting, step 270, id 0xb]
So you have my same problem...is little comforting..:-) I use the Jakarta Tomcat 5.0.28 and Sun Solaris 10, so how can proceed now?? I suppose that i must wait for the OOo 2.0.4 (when it will be released?) There isn't another way??
@sw: Sorry but what means "can't be closed"? Does it refuse? Does it crash? From former comments I assume it's the latter but please let me know if I'm right. If it crashes: did you create a crash report?
I think that "can't be closed" means that OO don't close property calling the method xClose.close(true), the document is created correctly, but OO crashes when i try to invoke the method..
So to Stephan: can you provide a crash report?
seems to be a lot more work to do
There are any news??? This problem is mission-critical for our application...
No news; Stephan is no longer with us and until now nobody else had the time to take over. Perhaps you can speed up things by describing shortly what needs to be set up to reproduce the problem (as distilling this information out from the issue surely is a tedious and longish procedure). Can we reproduce the problem with a standalone Java application (did you try?) or do we need to have a Web server installed (what most developer machines don't have). Did you try the same with a recent OOo version?
Sorry...i post the same message two times... I tried also with 2.1 but the problem is the same... I have posted in a zip, an example of the issue, as i said time ago, the problem is the image in the footer..
set target from 2.x to 3.x according to http://wiki.services.openoffice.org/wiki/Target_3x
Reset assigne to the default "issues@openoffice.apache.org".