Open enragedginger opened 2 years ago
tl;dr Is PAOS or one of its dependencies modifying default behavior for some underlying XML classes?
It looks like the issue I've encountered is that paos / selmer is expecting the XML string to not have any CDATA references in it.
I made a new project that only has Clojure 1.11.1 and [org.clojure/data.xml "0.2.0-alpha6"]
as dependencies.
I can start a REPL for this project and evaluate this code:
(ns xml-much.core
(:require [clojure.data.xml :as data-xml]))
(def data
#xml/element{:tag :soapenv:Envelope,
:attrs #:xmlns.http%3A%2F%2Fwww.w3.org%2F2000%2Fxmlns%2F{:soapenv "http://schemas.xmlsoap.org/soap/envelope/"},
:content [[#clojure.data.xml.node.CData{:content "{% with ctx=Envelope %}"}]]})
(data-xml/indent-str data)
(data-xml/emit-str data)
The output looks something like this:
=> #'xml-much.core/data
=>
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><![CDATA[{% with ctx=Envelope %}]]></soapenv:Envelope>
"
=>
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><![CDATA[{% with ctx=Envelope %}]]></soapenv:Envelope>"
Notice that the CDATA blocks are present for both outputs.
However, if I add paos to my dependencies, [io.xapix/paos "0.2.5"]
, and rerun the same code, I get this output instead:
=> #'xml-much.core/data
=>
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">{% with ctx=Envelope %}</soapenv:Envelope>"
=>
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><![CDATA[{% with ctx=Envelope %}]]></soapenv:Envelope>"
Notice that the output from indent-str
no longer has the CDATA
block.
It looks like something in paos or its dependency tree is modifying some underlying Java XML class or configuration in a way that changes how clojure.data.xml/indent-str renders CDATA blocks. Any ideas on what this may be or how it can be avoided?
I've trimmed down my use-case as much as possible to make this as easy as possible to debug. But my real world use case involves pulling in a number of other dependencies and one of those dependencies is somehow not interfering with this assumption made by paos when I run my app from the REPL, but interferes / prevents this assumption from making its way into any uberjar I build.
I managed to figure out what was going on here.
indenting-transformer
in clojure.data.xml.jvm.pprint
calls (TransformerFactory/newInstance)
when generating indented XML. Behind the scenes, the factory checks a few different places when trying to decide which impl it should return.
By default, you get com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
which prints the CDATA entities as-is. paos pulls in saxon which has net.sf.saxon.TransformerFactoryImpl
and expects that instance to be used instead of the JVM default as this transformer doesn't print the CDATA tags (as selmer doesn't know what to do with these tags).
So for my app, I can just do this for now to work around the issue: (System/setProperty "javax.xml.transform.TransformerFactory" "net.sf.saxon.TransformerFactoryImpl")
But this means that anything else in my app's JVM that requires a different TransformerFactory
implementation might have a bad time.
Any suggestions on how we can ensure that others avoid this situation with this library in the future?
Hello,
I've been happily running version 0.2.4 of this library for awhile now. Recently, things stopped working altogether in the production Docker container. I'm seeing some strange behavior and I'm not sure how to track down the root cause.
I load a WSDL file as a classpath resource and pass it to
paos.wsdl/parse
. This passes. I grab my reified service instance from the wsdl service object without issue. I call(paos.service/request-template service)
. Locally, the template looks normal and has blocks like this:{% with ctx=Envelope %}{% with ctx=ctx.Header %}
. But in the Docker container, it looks something like this:<![CDATA[{% with ctx=Envelope %}]><![CDATA[{% with ctx=ctx.Header %}]>
.Locally, when I try to substitute my parameters into the template using
(service/wrap-body service body)
, the substitution happens properly. But when this call is performed inside of the Docker container, the parameter values are not substituted, and the<![CDATA[]]>
blocks remain, so it looks something like this:<![CDATA[]]><![CDATA[]]>
As best as I can tell, both environments are using JDK17, the same JARs (lein is being used to pull the JARs for both environments), and Clojure 1.11.1.
Any ideas on what's going on here or what I can do to troubleshoot this?
EDIT: I've narrowed this down a bit. Something is happening with the artifact produced by the
lein uberjar
task that causes it to produce different output for the aforementioned task than what happens via thelein repl
. Neither Docker nor the JDK appear to be at fault here.