Bug #6464
openSaxon prints stack trace when MessageListener throws an exception
0%
Description
Let's say I make the following minimal Java program, which throws a RuntimeException
whenever there is an xsl:message
:
package com.realtaonline.render.utils;
import java.io.File;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.stream.StreamSource;
import net.sf.saxon.s9api.MessageListener2;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.s9api.XsltCompiler;
import net.sf.saxon.s9api.XsltExecutable;
import net.sf.saxon.s9api.XsltTransformer;
public class Transformer {
public static void main(String[] args) throws Exception {
Processor proc = new Processor(true);
XsltCompiler compiler = proc.newXsltCompiler();
RealtaMessageListener listener = new RealtaMessageListener();
StreamSource ssource = new StreamSource(new File(args[0]));
XsltExecutable executable = compiler.compile(ssource);
XsltTransformer transformer = executable.load();
transformer.setMessageListener(listener);
transformer.setSource(new StreamSource(new File(args[1])));
transformer.setDestination(proc.newSerializer(new File(args[2])));
try {
transformer.transform();
} catch (RuntimeException e) {
System.out.println("We caught the exception, nothing to see here");
}
}
public static class RealtaMessageListener implements MessageListener2 {
public void message(XdmNode content, QName errorCode, boolean terminate,
SourceLocator locator) {
throw new RuntimeException("Transform aborted by xsl:message #1");
}
}
}
As you see, we catch the RuntimeException
at the top level, so the only output should be the line saying we caught it.
However, if I run that with this XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/">
<xsl:message terminate="true">
Whoooo
</xsl:message>
</xsl:template>
</xsl:stylesheet>
the output I get is:
MacBook-Pro-3:java larsga$ java -cp xmlserver/target/xmlserver-1.0-SNAPSHOT-jar-with-dependencies.jar com.realtaonline.render.utils.Transformer ~/tmp/tst.xsl ~/tmp/tst.xsl ~/tmp/out.xml
java.lang.RuntimeException: Transform aborted by xsl:message #1
at com.realtaonline.render.utils.Transformer$RealtaMessageListener.message(Transformer.java:44)
at net.sf.saxon.s9api.AbstractXsltTransformer.lambda$setMessageListener$0(AbstractXsltTransformer.java:305)
at net.sf.saxon.expr.instruct.MessageInstr$MessageInstrElaborator.lambda$elaborateForPush$0(MessageInstr.java:351)
at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:376)
at net.sf.saxon.trans.Mode.handleRuleNotNull(Mode.java:587)
at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:521)
at net.sf.saxon.trans.XsltController.applyTemplates(XsltController.java:684)
at net.sf.saxon.s9api.AbstractXsltTransformer.applyTemplatesToSource(AbstractXsltTransformer.java:430)
at net.sf.saxon.s9api.XsltTransformer.transform(XsltTransformer.java:358)
at com.realtaonline.render.utils.Transformer.main(Transformer.java:33)
We caught the exception, nothing to see here
So clearly Saxon is printing the stack trace when it catches the exception, before passing it on.
These stack traces appear in our consoles and logs and confuse people into thinking there actually is something wrong in cases where there isn't. It would be great if you could fix this.
Updated by Martin Honnen 6 months ago
I think you are seeing https://www.saxonica.com/html/documentation12/javadoc/net/sf/saxon/lib/StandardLogger.html writing to System.err. You can set up a different Logger to write to a File or PrintStream or Writer or discard anything. See https://www.saxonica.com/html/documentation12/javadoc/net/sf/saxon/Configuration.html#setLogger(net.sf.saxon.lib.Logger).
Updated by Lars Marius Garshol 6 months ago
Thank you for the input, Martin. I tried it by implemented a Logger:
package com.realtaonline.render.xmlserver;
import net.sf.saxon.lib.Logger;
public class RealtaLogger extends Logger {
public void println(String message, int severity) {
}
public void warning(String message) {
}
public void info(String message) {
}
public void error(String message) {
}
public void disaster(String message) {
}
}
and added two lines to set it in the configuration:
public static void main(String[] args) throws Exception {
Processor proc = new Processor(true);
Configuration cfg = proc.getUnderlyingConfiguration();
cfg.setLogger(new RealtaLogger());
XsltCompiler compiler = proc.newXsltCompiler();
The output is exactly the same as before. So the message is clearly not coming from a Logger.
Updated by Michael Kay 5 months ago
I have so far failed to reproduce the problem.
Could you clarify which version of Saxon you are using?
Updated by Michael Kay 5 months ago
- Subject changed from Saxon prints stack trace to console to Saxon prints stack trace when MessageListener throws an exception
Updated by Lars Marius Garshol 5 months ago
Running “net.sf.saxon.Transform -versionmsg” on the jar I that contains the minimal test case:
SaxonJ-PE 12.4 from Saxonica
On my disk it’s:
MacBook-Pro-3:java larsga$ ll ../jar/saxonpe/saxonpe.jar
-rw-r--r-- 1 larsga staff 6422837 Dec 21 2023 ../jar/saxonpe/saxonpe.jar
MacBook-Pro-3:java larsga$ sha1sum $_
d9877062db0c5b876c3b5c46de13066235d03eea ../jar/saxonpe/saxonpe.jar
MacBook-Pro-3:java larsga$
Please register to edit this issue