I am working with an API that requires all SOAP calls to be signed. I have looked into the documentation from Java on how to sign SOAP calls using Programming With the Java XML Digital Signature API.
I am consistently running into the following error java.lang.IllegalArgumentException: No matching method found: newCanonicalizationMethod for class org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.
I know that the issue is with sending the parameters to the newCanonocalizationMethod. I am following the flow per Java, but I am still running into this issue.
Here is my code.
(let [fac (XMLSignatureFactory/getInstance "DOM")
dm (doto (.. fac (newDigestMethod (DigestMethod/SHA1) nil)))
bk ""
ref (.. fac (newReference bk dm))
cm (CanonicalizationMethod/INCLUSIVE)
c14 C14NMethodParameterSpec
in (.. fac (newCanonicalizationMethod cm c14))])
Here is the full function code: I have just started the process of creating the signature section per this site: http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html
(defn create-signature
[]
(let [fac (XMLSignatureFactory/getInstance "DOM")
dm (doto (.. fac (newDigestMethod (DigestMethod/SHA1) nil)))
bk ""
ref (.. fac (newReference bk dm))
cm CanonicalizationMethod/INCLUSIVE
c14 C14NMethodParameterSpec
si (..
fac
(newSignedInfo
(..
fac
(newCanonicalizationMethod
cm
C14NMethodParameterSpec))
(..
fac
(newSignatureMethod
(SignatureMethod/RSA_SHA1) nil))
(.. java.util.Collections (singletonList ref))))
]
))
If you run reflect on the factory, you get this as a response:
{:name newCanonicalizationMethod,
:return-type javax.xml.crypto.dsig.CanonicalizationMethod,
:declaring-class
org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory,
:parameter-types
[java.lang.String
javax.xml.crypto.dsig.spec.C14NMethodParameterSpec],
:exception-types
[java.security.NoSuchAlgorithmException
java.security.InvalidAlgorithmParameterException],
:flags #{:public}}
The solution to this issue was to generate all of the java methods in a custom Java class. The issue was the Java method was looking for a certain type of parameter. The code says to generate it using (Java type)null, which doesn't compile in Clojure.
I was using this website to generate the XML signing link.
After creating the custom class, I compiled and imported into the Clojure project.
Lesson Learned: When working with certain java classes, it is best to use pure Java instead of Java Interop.