Skip to content

Commit 290659f

Browse files
Fix xpath factory in multiple threads
RISDEV-0000
1 parent 472dcf5 commit 290659f

File tree

1 file changed

+12
-6
lines changed
  • backend/src/main/java/de/bund/digitalservice/ris/norms/utils

1 file changed

+12
-6
lines changed

backend/src/main/java/de/bund/digitalservice/ris/norms/utils/NodeParser.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616

1717
/** Util class that is responsible for parsing a {@link Node}. */
1818
public final class NodeParser {
19-
private static XPathFactory xPathFactory = XPathFactory.newInstance();
19+
// the XPathFactory is not thread safe so every thread gets its own one. It should not be a
20+
// problem that we do not call remove() on it as it can be reused even after returning the thread
21+
// to a ThreadPool.
22+
private static final ThreadLocal<XPathFactory> xPathFactory =
23+
ThreadLocal.withInitial(XPathFactory::newInstance);
2024

2125
private NodeParser() {
2226
// Should not be instantiated as an object
@@ -45,7 +49,7 @@ public static Optional<String> getValueFromExpression(String xPathExpression, No
4549

4650
// should be invoked on every method call since: An XPath object is not thread-safe and not
4751
// reentrant.
48-
final XPath xPath = xPathFactory.newXPath();
52+
final XPath xPath = xPathFactory.get().newXPath();
4953
String result = (String) xPath.evaluate(xPathExpression, sourceNode, XPathConstants.STRING);
5054
return result.isEmpty() ? Optional.empty() : Optional.of(result);
5155
} catch (XPathExpressionException | NoSuchElementException e) {
@@ -80,9 +84,12 @@ public static List<Node> getNodesFromExpression(String xPathExpression, Node sou
8084
try {
8185
// should be invoked on every method call since: An XPath object is not thread-safe and not
8286
// reentrant.
83-
final XPath xPath = XPathFactory.newInstance().newXPath();
8487
final NodeList nodeList =
85-
(NodeList) xPath.evaluate(xPathExpression, sourceNode, XPathConstants.NODESET);
88+
(NodeList)
89+
xPathFactory
90+
.get()
91+
.newXPath()
92+
.evaluate(xPathExpression, sourceNode, XPathConstants.NODESET);
8693
return nodeListToList(nodeList);
8794
} catch (XPathExpressionException | NoSuchElementException e) {
8895
throw new XmlProcessingException(e.getMessage(), e);
@@ -100,8 +107,7 @@ public static List<Node> getNodesFromExpression(String xPathExpression, Node sou
100107
*/
101108
public static Optional<Node> getNodeFromExpression(String xPathExpression, Node sourceNode) {
102109
try {
103-
final XPathFactory xpathfactory = XPathFactory.newInstance();
104-
final XPath xpath = xpathfactory.newXPath();
110+
final XPath xpath = xPathFactory.get().newXPath();
105111
final var result = xpath.evaluate(xPathExpression, sourceNode, XPathConstants.NODE);
106112
if (result instanceof Node node) {
107113
return Optional.of(node);

0 commit comments

Comments
 (0)