Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error with <![CDATA[]]> present in output template #24

Open
enragedginger opened this issue Apr 20, 2022 · 2 comments
Open

Error with <![CDATA[]]> present in output template #24

enragedginger opened this issue Apr 20, 2022 · 2 comments

Comments

@enragedginger
Copy link

enragedginger commented Apr 20, 2022

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.

@enragedginger enragedginger changed the title Error with !CDATA[] present in output template Error with <![CDATA[]]> present in output template Apr 20, 2022
@enragedginger
Copy link
Author

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.

@enragedginger
Copy link
Author

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant