I am using Apache POI (version 5.2.2) Java library to replace text placeholders in word documents. One of my task is to replace/edit text put in a rectangle shape. I am using the code below and it successfully works, the only issue that I am facing is that if I am to change or edit some other paragraph's text in the document then it is giving an exception. The codes and the exception is given below.
The code to change the text box content:
private void replacePlaceholdersWithInAShape(XWPFParagraph paragraph) throws XmlException {
XmlCursor cursor = paragraph.getCTP().newCursor();
cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:txbxContent/w:p/w:r");
List<XmlObject> ctrsintxtbx = new ArrayList<XmlObject>();
while(cursor.hasNextSelection()) {
cursor.toNextSelection();
XmlObject obj = cursor.getObject();
ctrsintxtbx.add(obj);
}
for (XmlObject obj : ctrsintxtbx) {
CTR ctr = CTR.Factory.parse(obj.xmlText());
XWPFRun bufferrun = new XWPFRun(ctr, (IRunBody)paragraph);
String text = bufferrun.getText(0);
if (text != null && !text.equalsIgnoreCase("")) {
if(text.contains("[{project_number}]")) {
System.out.println("contains project number");
text = text.replace("[{project_number}]", "test");
bufferrun.setText("test", 0);
} else {
bufferrun.setText(text, 0);
}
}
obj.set(bufferrun.getCTR());
}
}
The code use to change the paragraph text after successfully editing the text in the text box/shape
protected void replaceParagraphPlaceholders(String paraText, XWPFParagraph paragraph, String key, String value, Map<String, Object> fields) {
//paragraph text's empty and null check.
String paragraphText = paragraph.getText();
if(paragraphText!=""&¶graphText!=null) {
if(paragraph.getRuns().size()<=1) {
String runText = "Sample text";
paragraph.getRuns().get(0).setText(runText, 0);
}
}
}
The exception coming from the above code while changing the paragraph text is as below.
java.util.ConcurrentModificationException: Document changed during select
at org.apache.xmlbeans.impl.xpath.xmlbeans.XmlbeansXPathEngine.next(XmlbeansXPathEngine.java:100)
at org.apache.xmlbeans.impl.store.Cursor._toSelection(Cursor.java:749)
at org.apache.xmlbeans.impl.store.Cursor._getSelectionCount(Cursor.java:764)
at org.apache.xmlbeans.impl.store.Cursor.notifyChange(Cursor.java:697)
at org.apache.xmlbeans.impl.store.Locale.notifyChange(Locale.java:995)
at org.apache.xmlbeans.impl.store.Cur.moveChars(Cur.java:1772)
at org.apache.xmlbeans.impl.store.Cur.moveNodeContents(Cur.java:2016)
at org.apache.xmlbeans.impl.store.Cur.moveNodeContents(Cur.java:1986)
at org.apache.xmlbeans.impl.store.Xobj.store_text(Xobj.java:1833)
at org.apache.xmlbeans.impl.values.XmlObjectBase.set_String(XmlObjectBase.java:1106)
at org.apache.xmlbeans.impl.values.XmlObjectBase.setStringValue(XmlObjectBase.java:1774)
at org.apache.poi.xwpf.usermodel.XWPFRun.setText(XWPFRun.java:363)
at net.sharesuite.formletter.builder.poibuilder.docx.PoiDocxBuilder.replaceParagraphPlaceholders(PoiDocxBuilder.java:596)
at net.sharesuite.formletter.builder.poibuilder.docx.PoiDocxBuilder.lambda$1(PoiDocxBuilder.java:205)
at java.base/java.util.ArrayList$Itr.forEachRemaining(ArrayList.java:1003)
at java.base/java.util.Collections$UnmodifiableCollection$1.forEachRemaining(Collections.java:1061)
at net.sharesuite.formletter.builder.poibuilder.docx.PoiDocxBuilder.createFormLetterFile(PoiDocxBuilder.java:175)
at net.sharesuite.formletter.service.impl.FormLetterServiceImpl.createFormLetter(FormLetterServiceImpl.java:42)
at net.sharesuite.test.formletter.DocumentTest.testNLBLFormletter(DocumentTest.java:646)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Once the document's text is changed using the XMLObject, other changes in the document's paragraph etc. is causing the above exception.