<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Katrin Grunert</title>
    <description>The latest articles on DEV Community by Katrin Grunert (@erewl).</description>
    <link>https://dev.to/erewl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F484243%2F0e44837c-af1b-41d1-a8c5-402a2fb52c3a.jpg</url>
      <title>DEV Community: Katrin Grunert</title>
      <link>https://dev.to/erewl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/erewl"/>
    <language>en</language>
    <item>
      <title>Signing and verifying SOAP messages with wss4j and Scala</title>
      <dc:creator>Katrin Grunert</dc:creator>
      <pubDate>Tue, 29 Jun 2021 09:01:51 +0000</pubDate>
      <link>https://dev.to/vandebron/signing-and-verifying-soap-messages-with-wss4j-and-scala-p6a</link>
      <guid>https://dev.to/vandebron/signing-and-verifying-soap-messages-with-wss4j-and-scala-p6a</guid>
      <description>&lt;h1&gt;
  
  
  Signing and verfiying SOAP messages with wss4j and Scala
&lt;/h1&gt;

&lt;p&gt;SOAP is not dead. It is an established, XML-based and mature messaging protocol that comes with built-in security mechanisms, integrity checks, content validation and much more. A lot of enterprises and corporations are using it &lt;del&gt;sadly&lt;/del&gt; still.&lt;br&gt;
Just recently, Vandebron had to implement a SOAP client to communicate with an external party. &lt;br&gt;
This blog post will explain with code examples how we at Vandebron are signing and verifying SOAP messages for our latest SOAP client implementation. &lt;/p&gt;

&lt;p&gt;For this process, we are using Apache's Web Service Security Library &lt;a href="https://ws.apache.org/wss4j/"&gt;wss4j&lt;/a&gt; as it is a proven tool in the WSS context and provides, as a Java library, great interoperability with the programming language Scala.&lt;/p&gt;
&lt;h2&gt;
  
  
  Signing SOAP messages
&lt;/h2&gt;

&lt;p&gt;Here we will take a look at the necessary steps to sign a SOAP message like this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;soapenv:Envelope&lt;/span&gt; &lt;span class="na"&gt;xmlns:soapenv=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.xmlsoap.org/soap/envelope/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;soapenv:Header/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;soapenv:Body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;heading&amp;gt;&lt;/span&gt;Hello World&lt;span class="nt"&gt;&amp;lt;/heading&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;I am just a test&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/soapenv:Body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/soapenv:Envelope&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To look after signing like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;soapenv:Envelope&lt;/span&gt; &lt;span class="na"&gt;xmlns:soapenv=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.xmlsoap.org/soap/envelope/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;soapenv:Header&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;wsse:Security&lt;/span&gt; 
    &lt;span class="na"&gt;soapenv:mustUnderstand=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="na"&gt;xmlns:wsu=&lt;/span&gt;&lt;span class="s"&gt;"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&lt;/span&gt; &lt;span class="na"&gt;xmlns:wsse=&lt;/span&gt;&lt;span class="s"&gt;"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ds:Signature&lt;/span&gt; 
      &lt;span class="na"&gt;Id=&lt;/span&gt;&lt;span class="s"&gt;"SIG-ec946953-2470-4689-ad2f-0c579e1e06e3"&lt;/span&gt; &lt;span class="na"&gt;xmlns:ds=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/09/xmldsig#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ds:SignedInfo&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;ds:CanonicalizationMethod&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/10/xml-exc-c14n#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;ec:InclusiveNamespaces&lt;/span&gt; &lt;span class="na"&gt;PrefixList=&lt;/span&gt;&lt;span class="s"&gt;"soapenv"&lt;/span&gt; &lt;span class="na"&gt;xmlns:ec=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/10/xml-exc-c14n#"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/ds:CanonicalizationMethod&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;ds:SignatureMethod&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;ds:Reference&lt;/span&gt; &lt;span class="na"&gt;URI=&lt;/span&gt;&lt;span class="s"&gt;"#id-47817454-f6e2-470c-9109-870e7895e3e0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;ds:Transforms&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;ds:Transform&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/10/xml-exc-c14n#"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/ds:Transforms&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;ds:DigestMethod&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/04/xmlenc#sha256"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;ds:DigestValue&amp;gt;&lt;/span&gt;7KfPcTwDYWtLj4ZVWmWmVqX4IGwbBAAmUPigCdXdk4U=&lt;span class="nt"&gt;&amp;lt;/ds:DigestValue&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/ds:Reference&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/ds:SignedInfo&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ds:SignatureValue&amp;gt;&lt;/span&gt;
          OBnbBWv8S70xDDn5uG++7cTRFa2Uz3D47oxTHuO163Y3/V7H35M1GHXbKaUDOHsgsfx3SdVmVi++ra06cpwJknzqoIQgDV9Qc0ydzfxljCqupPKBnfONDYJtihEE1jtQ0RP7OLzPVNUpgOgHqbLwJu2pRUA05ool+lxIs924OwPVPKyUryoYwWhwY1ttY4P+WY2L3ZqsH3fgoLCyjlvhDEAhsP9PCxsEzPSq3ECC55Nh7nqMoHPj2uNxonuMlPeYbrlMnwyiqEW8s3Sc+WmfiIOgekRE1AdNhpn3ARlO490nObQtXCU/TxeTfbh98TMbQRZWWyT4HuLS3fF6aeyD/Q==
        &lt;span class="nt"&gt;&amp;lt;/ds:SignatureValue&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ds:KeyInfo&lt;/span&gt; &lt;span class="na"&gt;Id=&lt;/span&gt;&lt;span class="s"&gt;"KI-e18395de-9a26-4cad-9501-7c6cf6c7c74a"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;wsse:SecurityTokenReference&lt;/span&gt; &lt;span class="na"&gt;wsu:Id=&lt;/span&gt;&lt;span class="s"&gt;"STR-daa47836-f1f9-4d71-95cc-b7bcc6051c84"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;wsse:KeyIdentifier&lt;/span&gt; 
            &lt;span class="na"&gt;ValueType=&lt;/span&gt;&lt;span class="s"&gt;"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier"&lt;/span&gt; &lt;span class="na"&gt;EncodingType=&lt;/span&gt;&lt;span class="s"&gt;"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
              ox4ajWTdigy9oApTYs97CuCV/4k=
            &lt;span class="nt"&gt;&amp;lt;/wsse:KeyIdentifier&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/wsse:SecurityTokenReference&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/ds:KeyInfo&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/ds:Signature&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/wsse:Security&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/soapenv:Header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;soapenv:Body&lt;/span&gt; 
    &lt;span class="na"&gt;wsu:Id=&lt;/span&gt;&lt;span class="s"&gt;"id-47817454-f6e2-470c-9109-870e7895e3e0"&lt;/span&gt; &lt;span class="na"&gt;xmlns:wsu=&lt;/span&gt;&lt;span class="s"&gt;"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;heading&amp;gt;&lt;/span&gt;Hello World&lt;span class="nt"&gt;&amp;lt;/heading&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;I am just a test&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/soapenv:Body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/soapenv:Envelope&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For implementing the steps of the blog post you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a SOAP service you want to send messages to&lt;/li&gt;
&lt;li&gt;documentation of that SOAP service that describes:

&lt;ul&gt;
&lt;li&gt;signature algorithm&lt;/li&gt;
&lt;li&gt;canonicalization method&lt;/li&gt;
&lt;li&gt;digest algorithm&lt;/li&gt;
&lt;li&gt;key identifier type&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;a private key with which you will sign your messages&lt;/li&gt;
&lt;li&gt;a certificate that is the counterpart of the private key&lt;/li&gt;
&lt;li&gt;(optional) a pool of trusted certificates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our private and public key pair are available in the PKCS#12-format (.p12 file extension). Check out &lt;a href="https://www.ssl.com/how-to/create-a-pfx-p12-certificate-file-using-openssl/"&gt;this&lt;/a&gt; to learn more about this format and how to achieve it.&lt;br&gt;
The pool of trusted certificates are in the &lt;a href="https://www.ssl.com/guide/pem-der-crt-and-cer-x-509-encodings-and-conversions/"&gt;PKCS#7 format&lt;/a&gt; (.p7b file extension).&lt;/p&gt;

&lt;p&gt;First we have to setup the necessary dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;   &lt;span class="c1"&gt;// in your build.sbt or project/Dependencies.scala&lt;/span&gt;
  &lt;span class="c1"&gt;// enabling signing and signature verification for SOAP messages&lt;/span&gt;
  &lt;span class="k"&gt;lazy&lt;/span&gt; &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;webServiceSecurity&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Seq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"org.apache.wss4j"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"wss4j"&lt;/span&gt;                    &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"2.3.1"&lt;/span&gt; &lt;span class="nf"&gt;pomOnly&lt;/span&gt; &lt;span class="o"&gt;(),&lt;/span&gt;
    &lt;span class="s"&gt;"org.apache.wss4j"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"wss4j-ws-security-dom"&lt;/span&gt;    &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"2.3.1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"org.apache.wss4j"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"wss4j-ws-security-common"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"2.3.1"&lt;/span&gt;
  &lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;libraryDependencies&lt;/span&gt; &lt;span class="o"&gt;++=&lt;/span&gt; &lt;span class="n"&gt;webServiceSecurity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we continue with a scala representation of our certificate we are using for signing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.wss4j.dom.WSConstants&lt;/span&gt;

  &lt;span class="c1"&gt;// algorithm configuration&lt;/span&gt;
  &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;SigningCertificate&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;CanonicalizationMethodURI&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://www.w3.org/2001/10/xml-exc-c14n#"&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;DigestAlgorithmURI&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;DigestMethod&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;SHA256&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;SignatureAlgorithmURI&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;KeyIdentifierType&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;WSConstants&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;SKI_KEY_IDENTIFIER&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SigningCertificate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyStore&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;KeyStore&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="nv"&gt;keyStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;aliases&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="py"&gt;asScala&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="s"&gt;"Certificate of Keystore needs to have one alias but had ${keyStore.aliases().asScala.size}"&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;alias&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;keyStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;aliases&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="py"&gt;nextElement&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="s"&gt;"SigningCertificate(alias=$alias)"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the documentation of the SOAP service that you want to call should stand some information regarding the canonicalization method, signature algorithm, digest algorithm, and the key identifier type. Those are algorithms and information that define the signing process and we explain roughly now.&lt;/p&gt;

&lt;p&gt;Before signing a message it has to be canonicalized. "Canonicalization is a method for generating a physical representation, the canonical form, of an XML document that accounts for syntactic changes permitted by the XML specification" (from &lt;a href="https://www.di-mgt.com.au/xmldsig-c14n.html"&gt;here&lt;/a&gt;). In our case, the Exclusive XML Canonicalization is used.&lt;/p&gt;

&lt;p&gt;The digest algorithm is used to ensure the integrity of the message during the verification of a signature. The algorithm is used to calculate a hash of the signed message. It should be documented in the SOAP service documentation. Here we will use SHA256 as a hashing algorithm.&lt;/p&gt;

&lt;p&gt;The signature algorithm describes how the message will be signed. It can be defined in the SOAP service documentation but in the worst case you can read this algorithm from the certificate itself by using &lt;a href="https://docs.oracle.com/en/java/javase/12/tools/keytool.html"&gt;&lt;code&gt;keytool&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ keytool -list -v -keystore signature.p12
Enter keystore password: ...

[...] # more information about the certificates

Signature algorithm name: SHA256withRSA # thats what we are after!

[...] # more information about the certificates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;According to the keytool inspection we will use SHA256withRSA (&lt;a href="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"&gt;http://www.w3.org/2001/04/xmldsig-more#rsa-sha256&lt;/a&gt;) for signing.&lt;/p&gt;

&lt;p&gt;Last but not least, in our signature, a &lt;code&gt;&amp;lt;KeyInfo&amp;gt;&lt;/code&gt; element is included. This element contains information about the public key of the sender (us) and is needed for the signature verification once the message is received (read more &lt;a href="https://www.xml.com/pub/a/2001/08/08/xmldsig.html"&gt;here&lt;/a&gt;). Since we have our public key provided we don't need to do much here. The &lt;code&gt;KeyIdentifierType&lt;/code&gt; describes which form of key identifier is used to present the public key information.&lt;/p&gt;

&lt;p&gt;Having all this information about our certificate in place, we build the mechanism to load in our signing certificate. For this, we create the object &lt;code&gt;KeyStoreBuilder&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;FileInputStream&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;KeyStoreBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;loadSigningCertificate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signingCertificate&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;File&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SigningCertificate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;fis&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signingCertificate&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;ks&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;KeyStore&lt;/span&gt;               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;KeyStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PKCS12"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;ks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fis&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toCharArray&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;SigningCertificate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ks&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bear in mind, that you probably &lt;strong&gt;don't&lt;/strong&gt; want to version any sensitive information like private keys and passwords hard-coded or in any environment variables, so a safe mechanism for storing/fetching passwords and certificates (like &lt;a href="https://www.hashicorp.com/products/vault"&gt;Vault&lt;/a&gt;) should be in place.&lt;/p&gt;

&lt;p&gt;With the signing certificate in place, we can actually start signing a message. The next code example contains quite some Java boilerplate from wss4j that is required to make the signing mechanism work.&lt;/p&gt;

&lt;p&gt;To restrict the usage of Java classes to a small portion of our code we will firstly implement a conversion method &lt;code&gt;.toElem&lt;/code&gt; inside of the companion object &lt;code&gt;SigningService&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.StringWriter&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.xml.transform.&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;OutputKeys&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;TransformerFactory&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.xml.transform.dom.DOMSource&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.xml.transform.stream.StreamResult&lt;/span&gt;

  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.w3c.dom.Document&lt;/span&gt;

  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;scala.xml.Elem&lt;/span&gt;

  &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;SigningService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RichDocument&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Document&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;tf&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;TransformerFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;newInstance&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;toElem&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Elem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;transformer&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;tf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;newTransformer&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="nv"&gt;transformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setOutputProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;OutputKeys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;OMIT_XML_DECLARATION&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"yes"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;stringWriter&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StringWriter&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="nv"&gt;transformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;transform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DOMSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StreamResult&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stringWriter&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="nv"&gt;scala&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;XML&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;loadString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;stringWriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getBuffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, we can convert any &lt;code&gt;Document&lt;/code&gt; SOAP message representation back to the &lt;code&gt;scala.xml&lt;/code&gt; supported  &lt;code&gt;Elem&lt;/code&gt; format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SigningService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signingCertificate&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SigningCertificate&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// importing our conversion method&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;SigningService.RichDocument&lt;/span&gt;

  &lt;span class="cm"&gt;/**
    * REQUIRED, otherwise it will throw:
    *
    * org.apache.wss4j.common.ext.WSSecurityException:
    * You must initialize the xml-security library correctly before you use it.
    * Call the static method "org.apache.xml.security.Init.init();"
    * to do that before you use any functionality from that library
    */&lt;/span&gt;
  &lt;span class="nv"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;apache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;security&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Init&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;init&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;documentBuilderFactory&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;DocumentBuilderFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;newInstance&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;crypto&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Merlin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getCrypto&lt;/span&gt;

  &lt;span class="nv"&gt;crypto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setKeyStore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;signingCertificate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;keyStore&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;signElement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Elem&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Elem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;documentBuilderFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setNamespaceAware&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// converting Elem to Document (Scala to Java conversion)&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;doc&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;documentBuilderFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;newDocumentBuilder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="py"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InputSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StringReader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;())))&lt;/span&gt;

    &lt;span class="c1"&gt;// WSSecHeader wraps around the document we want to sign&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;header&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WSSecHeader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setMustUnderstand&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;insertSecurityHeader&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// start building Signature, use the (wrapper) header-instance&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;builder&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WSSecSignature&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setUserInfo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;signingCertificate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;signingCertificate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// setting algorithms&lt;/span&gt;
    &lt;span class="nv"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setSignatureAlgorithm&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;SigningCertificate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;SignatureAlgorithmURI&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setSigCanonicalization&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;SigningCertificate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;CanonicalizationMethodURI&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setDigestAlgo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;SigningCertificate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;DigestAlgorithmURI&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setKeyIdentifierType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;SigningCertificate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;KeyIdentifierType&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setAddInclusivePrefixes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// signing the document!&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;signedDocument&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crypto&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// conversion back to Elem&lt;/span&gt;
    &lt;span class="nv"&gt;signedDocument&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toElem&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;getCrypto&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Merlin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;properties&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Properties&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="nv"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.apache.wss4j.crypto.provider"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"class org.apache.ws.security.components.crypto.Merlin"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;CryptoFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="py"&gt;asInstanceOf&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Merlin&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wss4j is a library that maintains an internal state during a signing process, but to avoid confusion it can be summarized as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;WSSecHeader&lt;/code&gt; wraps around the document to be signed&lt;/li&gt;
&lt;li&gt;the WSSecHeader instance &lt;code&gt;header&lt;/code&gt; will be used as part of the &lt;code&gt;WSSecSignature&lt;/code&gt;-Builder&lt;/li&gt;
&lt;li&gt;the WSSecSignature instance &lt;code&gt;builder&lt;/code&gt; gets configured with all necessary information, which algorithms are used for signing, digesting, canonicalization, which key identifier should be included. Those settings an vary from webservice to webservice.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The actual signing of the document, which is now nested like a matryoshka doll, is happening with the help of an instance of &lt;code&gt;Crypto&lt;/code&gt;. &lt;code&gt;Crypto&lt;/code&gt; will contain either a keystore or a truststore or even both. It needs to be specified in the &lt;code&gt;crypto.properties&lt;/code&gt; file or a runtime which class of Crypto will be used.&lt;br&gt;
 The most common one is &lt;a href="https://ws.apache.org/wss4j/apidocs/org/apache/wss4j/common/crypto/Merlin.html"&gt;&lt;code&gt;Merlin&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
We have decided to specify its configuration during runtime, since it is more visible than a properties file. Nevertheless, the &lt;code&gt;crypto.properties&lt;/code&gt;-file needs to exist in your &lt;code&gt;resources&lt;/code&gt; folder neverthless otherwise you will get a following &lt;code&gt;WSSecurityException&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;wss4j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;common&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;WSSecurityException&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;No&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="no"&gt;ID&lt;/span&gt; &lt;span class="s"&gt;"resourceNotFound"&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="s"&gt;"org/apache/xml/security/resource/xmlsecurity"&lt;/span&gt;
  &lt;span class="o"&gt;[...&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;stacktrace&lt;/span&gt; &lt;span class="o"&gt;...]&lt;/span&gt;
  &lt;span class="nl"&gt;Cause:&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NoSuchFileException&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;crypto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;properties&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! The &lt;code&gt;KeyStoreBuilder&lt;/code&gt; helps us to load a &lt;code&gt;SigningCertificate&lt;/code&gt; and the &lt;code&gt;SigningService&lt;/code&gt; uses this loaded certificate to sign SOAP messages. &lt;br&gt;
A receiver of our SOAP message has all the necessary information in our signature to verify that this message has not been tampered with and we are the original sender.&lt;/p&gt;

&lt;p&gt;This verification is something we should also do on our side for incoming messages. So let's take a look at how we can verify the signature of received messages.&lt;/p&gt;
&lt;h2&gt;
  
  
  Verification of SOAP messages
&lt;/h2&gt;

&lt;p&gt;Verifying the signature of incoming messages is equally important to ensure that the connection is secure. A verification process will tell you if the message is coming from a trusted source and has not been tampered with.&lt;/p&gt;

&lt;p&gt;As previously mentioned we need our source of truth, a pool of trusted public keys from all parties which will receive our SOAP messages. These build the basis of the trust store.&lt;/p&gt;

&lt;p&gt;We will create a &lt;code&gt;TrustedCertificates&lt;/code&gt; wrapper class in which we will load in the trust store and add this method to the &lt;code&gt;KeyStoreBuilder&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TrustedCertificates&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyStore&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;KeyStore&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;KeyStoreBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;loadTrustedCertificate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;certificates&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Seq&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;File&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;TrustedCertificates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;ks&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;KeyStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;KeyStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getDefaultType&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// we just want the keystore to act as a truststore (only containing trusted certificates), so we initialize it empty&lt;/span&gt;
    &lt;span class="nv"&gt;ks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;cf&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;CertificateFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"X.509"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;certificates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;foreach&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nv"&gt;CloseableUtil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;using&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getResourceAsStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getPath&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fis&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;certPath&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;cf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;generateCertPath&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fis&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"PKCS7"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;certPath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getCertificates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;asScala&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;foreach&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;certificate&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="nv"&gt;ks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setCertificateEntry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;certificate&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;TrustedCertificates&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ks&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This trust store is under the hood also just a KeyStore, without containing a private key that requires a password, that's why we can initialize the KeyStore with &lt;code&gt;null&lt;/code&gt;-parameters.&lt;/p&gt;

&lt;p&gt;Now, the SigningService needs to be extended with this trusted certificates and a &lt;code&gt;verifySignatureOf&lt;/code&gt;-method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.StringReader&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Properties&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.xml.parsers.DocumentBuilderFactory&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.wss4j.common.crypto.&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;CryptoFactory&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Merlin&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.wss4j.dom.engine.WSSecurityEngine&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.xml.sax.InputSource&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;scala.util.&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Failure&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Success&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Try&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;scala.xml.Elem&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SigningService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signingCertificate&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SigningCertificate&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trustedCertificates&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;TrustedCertificates&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;engine&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WSSecurityEngine&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;documentBuilderFactory&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;DocumentBuilderFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;newInstance&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;crypto&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Merlin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getCrypto&lt;/span&gt;

    &lt;span class="nv"&gt;crypto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setKeyStore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;signingCertificate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;keyStore&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;crypto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setTrustStore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;trustedCertificates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;keyStore&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;verifySignatureOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Elem&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;documentBuilderFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setNamespaceAware&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;doc&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;documentBuilderFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;newDocumentBuilder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="py"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InputSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StringReader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;())))&lt;/span&gt;

      &lt;span class="nc"&gt;Try&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;processSecurityHeader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crypto&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Success&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Failure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="c1"&gt;// replace with proper logging&lt;/span&gt;
          &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="s"&gt;"Unsuccessful signature verification, it is most likely that the certificate used for signing is not in our Truststore: ${exception.getMessage}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
          &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;getCrypto&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Merlin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;properties&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Properties&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="nv"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.apache.wss4j.crypto.provider"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"class org.apache.ws.security.components.crypto.Merlin"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;CryptoFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="py"&gt;asInstanceOf&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Merlin&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And with that, we have completed our roundtrip of signing and verifying SOAP messages!&lt;/p&gt;

&lt;p&gt;Here are gists, articles, and documentation that inspired and helped us to figure out the signing and verification process for our SOAP client. Feel free to check them out!&lt;/p&gt;




&lt;h3&gt;
  
  
  Sources
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/luiswolff/1d388ec8c1d63cfb58974a6f826bc1be"&gt;WSSecurityVerifier by Luis Wolff&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/luiswolff/64d15a99fbb5ec4b4e90eec04b09e053"&gt;WSSecuritySigner by Luis Wolff&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/apache/ws-wss4j/blob/master/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureTest.java"&gt;Unit Tests from ws-wss4j&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.xml.com/pub/a/2001/08/08/xmldsig.html"&gt;An Introduction to XML Digital Signatures&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackify.com/soap-vs-rest/"&gt;SOAP vs. REST&lt;/a&gt;&lt;/p&gt;

</description>
      <category>scala</category>
      <category>wss4j</category>
      <category>soap</category>
      <category>xml</category>
    </item>
    <item>
      <title>Building native images and compiling with GraalVM and sbt</title>
      <dc:creator>Katrin Grunert</dc:creator>
      <pubDate>Wed, 07 Oct 2020 11:05:34 +0000</pubDate>
      <link>https://dev.to/vandebron/building-native-images-and-compiling-with-graalvm-and-sbt-42dm</link>
      <guid>https://dev.to/vandebron/building-native-images-and-compiling-with-graalvm-and-sbt-42dm</guid>
      <description>&lt;p&gt;At Vandebron we organize a two-day long Hackathon every quarter, and a colleague and I took this chance to dig into the wonderful world of GraalVM.&lt;/p&gt;

&lt;p&gt;I've first heard of GraalVM around two years ago when Oleg Šelajev toured through Java User Groups in Germany and held talks about GraalVM. &lt;a href="https://www.youtube.com/watch?v=GinNxS3OSi0"&gt;Here&lt;/a&gt; is one from 2019 (not Germany, but Spain this time).&lt;/p&gt;

&lt;p&gt;GraalVM promises a significant speedup in compile times and as I am working with Scala, which is notoriously known for its long compile times, this seems interesting. Furthermore, GraalVM provides functionality to build native executables. Meaning, an application can be run without a Java Virtual Machine (JVM).&lt;/p&gt;

&lt;p&gt;Thanks to the Hackathon I finally took the time to get to know GraalVM a bit better. With this blog post, I want to share our findings, experiences, and results, as they might be helpful for you too!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is GraalVM?
&lt;/h2&gt;

&lt;p&gt;GraalVM is a high-performance JVM that supports efficient ahead-of-time (AOT) and just-in-time (JIT) compilation, but also allows non-JVM languages (e.g. Ruby, Python, C++) to run on the JVM. The ahead-of-time compilation feature is the base for creating native executable programs, meaning an application can be run independently from the JVM. Seeing the versatile features of GraalVM, it is worth looking a bit under its hood.&lt;/p&gt;

&lt;p&gt;Actually, GraalVM is defined by three main technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.graalvm.org/reference-manual/jvm/"&gt;Graal compiler&lt;/a&gt;, a high-performance JIT-compiler that can make JVM applications run faster from within the JVM&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.graalvm.org/reference-manual/native-image/SubstrateVM/"&gt;SubstrateVM&lt;/a&gt;, includes the necessary components to run a JVM-app as a native executable ( Garbage Collector, Thread Scheduler, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.graalvm.org/graalvm-as-a-platform/language-implementation-framework/"&gt;Truffle Language Implementation Framework&lt;/a&gt;, the basis for the polyglot support from GraalVM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our motivation for trying out GraalVM was tackling the pain points of Scala, Java projects, and microservices. Shipping microservices written in Scala as Docker containers to your production system comes with the cost that startup can be a bit slow, having JVM and Docker overhead, and that those containers can be fairly large, as the application can only be run with a JVM. See Building Docker images for more information.&lt;/p&gt;

&lt;p&gt;During the hackathon, we were most interested in building native images for Scala applications. Hoping to reduce the size of our docker containers and reducing up the startup time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project setup
&lt;/h2&gt;

&lt;p&gt;The project we worked on during the Hackathon is an API that should be used for applicants to submit their applications at Vandebron in the future. By exposing one endpoint through which a resume and contact information can be submitted.&lt;/p&gt;

&lt;p&gt;It is also a good project to test out GraalVM, nothing too complex but also not as simple as "Hello World".&lt;/p&gt;

&lt;p&gt;The full setup can be found &lt;a href="https://github.com/kgrunert/apply-at-vdb"&gt;on Github&lt;/a&gt;. But I'll summarise the used stack below. The project is built around the following libraries, no particular reason, simply because I like them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;cats&lt;/em&gt; for working with effects, such as IO&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;http4s&lt;/em&gt; for running the server&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;tapir&lt;/em&gt; for defining the endpoints&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;circe&lt;/em&gt; for JSON de/serialisation&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;pureconfig&lt;/em&gt; for reading config-files&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;logback&lt;/em&gt; for logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project can be run via &lt;code&gt;sbt run&lt;/code&gt; and with Postman or similar a POST-request can be sent like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;localhost:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="err"&gt;/api/v&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;/apply&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my@email.de"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My Name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"phoneNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+310123456789"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"applicationBase64"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VGhpcyBjb3VsZCBiZSB5b3VyIGFwcGxpY2F0aW9uIQ=="&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;Response:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"*confetti* Thanks for handing in your application, we will get back to you within the next days! *confetti*"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setup GraalVM with sbt
&lt;/h2&gt;

&lt;p&gt;With this initial project setup in mind, GraalVM needs to be installed locally.&lt;/p&gt;

&lt;p&gt;For the installation of GraalVM the &lt;a href="https://www.graalvm.org/docs/getting-started-with-graalvm/#install-graalvm"&gt;setup guide&lt;/a&gt; can be followed.&lt;/p&gt;

&lt;p&gt;After the installation sbt needs to know that not the regular JDK/JVM is used. This can be done with the &lt;code&gt;java-home&lt;/code&gt; option on sbt bootup.&lt;br&gt;
To make the path to GraalVM a bit more accessible and easy to use it can be exported as an environment variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GRAAL_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/Library/Java/JavaVirtualMachines/graalvm-ce-java8-20.1.0/Contents/Home
sbt &lt;span class="nt"&gt;-java-home&lt;/span&gt; &lt;span class="nv"&gt;$GRAALHOME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The path to GraalVM can vary depending on OS and installation. We followed the basic installation for macOS.&lt;/p&gt;

&lt;p&gt;Now sbt using GraalVM can be verified with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sbt &lt;span class="nt"&gt;-java-home&lt;/span&gt; &lt;span class="nv"&gt;$GRAALHOME&lt;/span&gt;
scala&amp;gt; &lt;span class="nb"&gt;eval &lt;/span&gt;System.getProperty&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"java.home"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;info] ans: String &lt;span class="o"&gt;=&lt;/span&gt; /Library/Java/JavaVirtualMachines/graalvm-ce-java8-20.1.0/Contents/Home/jre
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means everything running in this sbt instance is getting compiled by GraalVM. Awesome!&lt;/p&gt;

&lt;p&gt;The next step is to become strong and independent and learn how to run without an underlying JVM with the help of building native images.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building native images
&lt;/h2&gt;

&lt;p&gt;GraalVM ships with the &lt;a href="https://www.graalvm.org/reference-manual/graalvm-updater/"&gt;GraalVM Updater&lt;/a&gt; (&lt;code&gt;gu&lt;/code&gt;) to install the &lt;code&gt;native-image&lt;/code&gt; on your machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$GRAALHOME&lt;/span&gt;/bin/gu &lt;span class="nb"&gt;install &lt;/span&gt;native-image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://sbt-native-packager.readthedocs.io/en/latest/"&gt;sbt-native-packager&lt;/a&gt; provides functionality to build packages efficiently (e.g. building Docker images) and added to that, it also provides support for building native images.&lt;br&gt;
In order to build native images with sbt commands this plugin has to be added to the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="c1"&gt;// inside project/plugins.sbt&lt;/span&gt;
&lt;span class="nf"&gt;addSbtPlugin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.typesafe.sbt"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"sbt-native-packager"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"1.7.3"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the &lt;code&gt;GraalVMNativeImagePlugin&lt;/code&gt; needs to be enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="c1"&gt;// inside build.sbt&lt;/span&gt;
&lt;span class="nf"&gt;enablePlugins&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GraalVMNativeImagePlugin&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From within sbt it should be able to autocomplete and suggest graal-commands, e.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="n"&gt;sbt&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;apply-at-vdb&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;graalvm&lt;/span&gt;
&lt;span class="n"&gt;graalvm&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;native&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;       &lt;span class="kt"&gt;graalvmNativeImageOptions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that setup, native images are just a stone's throw away!&lt;/p&gt;




&lt;h3&gt;
  
  
  Disclaimer
&lt;/h3&gt;

&lt;p&gt;The next three sections are not a write-up but rather the main steps we had to take to make the project work. This includes failing images and troubleshooting.&lt;br&gt;
I want to keep this in because it might be interesting for others when they have to troubleshoot.&lt;br&gt;
For the summary and happy path, you can jump directly to Roundup.&lt;/p&gt;


&lt;h3&gt;
  
  
  First try building a native image
&lt;/h3&gt;

&lt;p&gt;Next up &lt;code&gt;graalvm-native-image:packageBin&lt;/code&gt; can be run from within sbt. This might take a while (on our systems it took about a minute)&lt;/p&gt;

&lt;p&gt;Some warnings start to pop up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[error] warning: unknown locality of class Lnl/vandebron/applyatvdb/Main$anon$exportedReader$macro$24$1;, assuming class is not local. To remove the warning report an issue to the library or language author. The issue is caused by Lnl/vandebron/applyatvdb/Main$anon$exportedReader$macro$24$1; which is not following the naming convention.

[error] warning: unknown locality of class Lfs2/internal/Algebra$Done$2$;, assuming class is not local. To remove the warning report an issue to the library or language author. The issue is caused by Lfs2/internal/Algebra$Done$2$; which is not following the naming convention.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The library-specific warnings can be ignored for now. Ultimately it fails with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: com.oracle.graal.pointsto.constraints.UnresolvedElementException:
Discovered unresolved type during parsing: org.slf4j.impl.StaticLoggerBinder.
To diagnose the issue you can use the --allow-incomplete-classpath option.
The missing type is then reported at run time when it is accessed the first time.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Actually a good hint on where to start fine-tuning the GraalVM config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="c1"&gt;// inside build.sbt&lt;/span&gt;
&lt;span class="n"&gt;graalVMNativeImageOptions&lt;/span&gt; &lt;span class="o"&gt;++=&lt;/span&gt; &lt;span class="nc"&gt;Seq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"--allow-incomplete-classpath"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some things like a &lt;code&gt;StaticLoggerBinder&lt;/code&gt; only get resolved at runtime, meaning at build time the classpath needs to be allowed to be incomplete. This option allows resolution errors to be ignored at build time and only pop up during runtime.&lt;/p&gt;

&lt;p&gt;During the build of a native image, GraalVM tries to resolve those runtime dependencies already at compile-time, as it is part of the Ahead-Of-Time-compilation process. With this flag, GraalVM knows "hey, don't worry about it now, we cross the bridge when we get there" (or something like that).&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding resource files
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;reload&lt;/code&gt; (or restart) of sbt is needed to activate these new options. And we can try to build the native image up new.&lt;br&gt;
This time the build finished successfully and the executable file &lt;code&gt;target/graalvm-native-image/apply-at-vdb&lt;/code&gt; has been created!&lt;br&gt;
This is an executable that can be run without a JVM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;target/graalvm-native-image/apply-at-vdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what's that? It actually cannot be started...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;target/graalvm-native-image/apply-at-vdb

SLF4J: Failed to load class &lt;span class="s2"&gt;"org.slf4j.impl.StaticLoggerBinder"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
SLF4J: Defaulting to no-operation &lt;span class="o"&gt;(&lt;/span&gt;NOP&lt;span class="o"&gt;)&lt;/span&gt; logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder &lt;span class="k"&gt;for &lt;/span&gt;further details.
&lt;span class="k"&gt;***&lt;/span&gt; An error occured! &lt;span class="k"&gt;***&lt;/span&gt;
Cannot convert configuration to a de.erewl.pricetracker.server.Config. Failures are:
at the root:
- Key not found: &lt;span class="s1"&gt;'host'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
- Key not found: &lt;span class="s1"&gt;'port'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first three lines relate to the error that occurred during the first build. It simply says that logging hasn't been set up correctly (maybe due to the absence of a &lt;code&gt;src/main/resources/logback.xml&lt;/code&gt; or some other misconfiguration), triggering the default setting of not logging anything at all.&lt;br&gt;
The second error states that a configuration file does not have the right keys or cannot be found at all.&lt;br&gt;
Looking into &lt;code&gt;src/main/resources&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;src/main/resources/
application.conf logback.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and peeking into &lt;code&gt;application.conf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;src/main/resources/application.conf
    host &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"localhost"&lt;/span&gt;
    port &lt;span class="o"&gt;=&lt;/span&gt; 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hm, so everything is actually in place. But somehow GraalVM can't find those files.&lt;br&gt;
It still requires some more GraalVM fine-tuning here.&lt;/p&gt;

&lt;p&gt;By default, GraalVM doesn't include any resource or configuration-files.&lt;br&gt;
The option &lt;code&gt;-H:ResourceConfigurationFiles=path/to/resource-config.json&lt;/code&gt; defines a path to a JSON configuration file. So inside the &lt;code&gt;resource-config.json&lt;/code&gt; we can include our &lt;code&gt;application.conf&lt;/code&gt; and our &lt;code&gt;logback.xml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But writing those config files can be tedious and it is difficult in larger projects to find all necessary classes that need to be included. GraalVM provides some support with writing those files and actually does all the work. In the project's root directory a configs-folder can be created which will contain all necessary config-files.&lt;/p&gt;

&lt;p&gt;For writing the configuration files we will build a normal JAR-file with the help of the &lt;code&gt;sbt-assembly&lt;/code&gt; plugin. Adding it to the project like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// inside project/plugins.sbt&lt;/span&gt;
  &lt;span class="nf"&gt;addSbtPlugin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.eed3si9n"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"sbt-assembly"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"0.14.6"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JAR-file will be built with &lt;code&gt;sbt assembly&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With that we can now start the application, providing the path to the JAR-file that just has been created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;configs
&lt;span class="nv"&gt;$GRAALHOME&lt;/span&gt;/bin/java &lt;span class="nt"&gt;-agentlib&lt;/span&gt;:native-image-agent&lt;span class="o"&gt;=&lt;/span&gt;config-output-dir&lt;span class="o"&gt;=&lt;/span&gt;./configs &lt;span class="nt"&gt;-jar&lt;/span&gt; target/scala-2.12/apply-at-vdb-assembly-0.1.0-SNAPSHOT.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the command above the JAR gets to run with GraalVM but adds &lt;a href="https://www.graalvm.org/reference-manual/native-image/Configuration/#assisted-configuration-of-native-image-builds"&gt;dynamic lookups&lt;/a&gt; that are being intercepted during runtime and written to the files: &lt;code&gt;jni-config.json&lt;/code&gt;, &lt;code&gt;proxy-config.json&lt;/code&gt;, &lt;code&gt;reflect-config.json&lt;/code&gt; and &lt;code&gt;resource-config.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Those generated files can be included in the GraalVMNativeImageOptions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="c1"&gt;// build.sbt&lt;/span&gt;
&lt;span class="n"&gt;graalVMNativeImageOptions&lt;/span&gt; &lt;span class="o"&gt;++=&lt;/span&gt; &lt;span class="nc"&gt;Seq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"--allow-incomplete-classpath"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-H:ResourceConfigurationFiles=../../configs/resource-config.json"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-H:ReflectionConfigurationFiles=../../configs/reflect-config.json"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-H:JNIConfigurationFiles=../../configs/jni-config.json"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-H:DynamicProxyConfigurationFiles=../../configs/proxy-config.json"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The build with those updated options should succeed and the app can be run once again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;target/graalvm-native-image/apply-at-vdb

SLF4J: Failed to load class &lt;span class="s2"&gt;"org.slf4j.impl.StaticLoggerBinder"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
SLF4J: Defaulting to no-operation &lt;span class="o"&gt;(&lt;/span&gt;NOP&lt;span class="o"&gt;)&lt;/span&gt; logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder &lt;span class="k"&gt;for &lt;/span&gt;further details.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still no logging, sadly. But the server is actually running and responds to POST requests via its exposed endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;localhost:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="err"&gt;/api/v&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;/apply&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my@email.de"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My Name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"phoneNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+310123456789"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"applicationBase64"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VGhpcyBjb3VsZCBiZSB5b3VyIGFwcGxpY2F0aW9uIQ=="&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;Response:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"*confetti* Thanks for handing in your application, we will get back to you within the next days! *confetti*"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next and last step will investigate why logging is not picked up by GraalVM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Investigating the missing logging
&lt;/h3&gt;

&lt;p&gt;So first I wanted to have a look if it was an overall issue with logging. I stepped back from using logging-framework and tried the most basic logging with the java-integrated &lt;code&gt;java.util.Logging&lt;/code&gt;. GraalVM's &lt;a href="https://www.graalvm.org/docs/Native-Image/user/LOGGING"&gt;docs&lt;/a&gt; stated that GraalVM supports any logging that depends on that.&lt;/p&gt;

&lt;p&gt;Building and running the native-image with &lt;code&gt;java.util.Logging&lt;/code&gt; instead of &lt;code&gt;logback&lt;/code&gt; succeeded and everything is logged properly.&lt;/p&gt;

&lt;p&gt;So it must be something with the dependencies?&lt;/p&gt;

&lt;p&gt;For further investigation, I added the &lt;a href="https://github.com/jrudolph/sbt-dependency-graph"&gt;sbt-dependency-graph&lt;/a&gt; plugin and checked out the dependency-tree with &lt;code&gt;sbt dependencyBrowserTree&lt;/code&gt;. The library &lt;code&gt;logback&lt;/code&gt; wasn't included in the dependency tree.&lt;br&gt;
Which is odd, since &lt;code&gt;logback&lt;/code&gt; is clearly present in the project's library-dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="c1"&gt;// inside build.sbt&lt;/span&gt;
&lt;span class="n"&gt;libraryDependencies&lt;/span&gt; &lt;span class="o"&gt;++=&lt;/span&gt; &lt;span class="nc"&gt;Seq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;"ch.qos.logback"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"logback-classic"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"1.2.3"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nc"&gt;Runtime&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"ch.qos.logback"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"logback-core"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"1.2.3"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nc"&gt;Runtime&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Having a closer look, the appendix &lt;code&gt;% Runtime&lt;/code&gt; on logback's dependency is present.&lt;/p&gt;

&lt;p&gt;Not sure where this was coming from but it is most probably blindly copy-pasted from somewhere when gathering the dependencies for this project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.scala-sbt.org/1.x/docs/Scopes.html#Scoping+by+the+configuration+axis"&gt;sbt reference manual&lt;/a&gt; states that the appendix &lt;code&gt;Runtime&lt;/code&gt; defines that this dependency will be only included in the runtime classpath.&lt;/p&gt;

&lt;p&gt;So this explains probably why logging was only working when the server was run from inside sbt.&lt;/p&gt;

&lt;p&gt;With removing this and building the native-image, &lt;code&gt;logback&lt;/code&gt; appears in the dependency-tree, and logging works when the native image is executed!&lt;/p&gt;

&lt;p&gt;This "bug" was interesting as it emphasized what GraalVM can NOT do for you. Dynamic class loading/linking can not be supported by GraalVM as classes and dependencies have to be present during compile time to make a fully functional application. &lt;/p&gt;

&lt;h3&gt;
  
  
  Roundup
&lt;/h3&gt;

&lt;p&gt;A successful setup of sbt and GraalVM to build native-images requires to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;install GraalVM's native-image functionality via it's graal-updater:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  gu &lt;span class="nb"&gt;install &lt;/span&gt;native-image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;add sbt-native-packager and sbt-assembly to sbt:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// inside project/plugins.sbt&lt;/span&gt;
  &lt;span class="nf"&gt;addSbtPlugin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.typesafe.sbt"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"sbt-native-packager"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"1.7.3"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;addSbtPlugin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.eed3si9n"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"sbt-assembly"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s"&gt;"0.14.6"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;enable the GraalVM-Plugin:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// inside build.sbt&lt;/span&gt;
  &lt;span class="nf"&gt;enablePlugins&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GraalVMNativeImagePlugin&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;create a fat JAR and define which resource and configuration files should be intergated by intercepting look up calls during its execution:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  sbt assembly
  &lt;span class="nb"&gt;mkdir &lt;/span&gt;configs
  &lt;span class="nv"&gt;$GRAALHOME&lt;/span&gt;/bin/java &lt;span class="nt"&gt;-agentlib&lt;/span&gt;:native-image-agent&lt;span class="o"&gt;=&lt;/span&gt;config-output-dir&lt;span class="o"&gt;=&lt;/span&gt;./configs &lt;span class="nt"&gt;-jar&lt;/span&gt; target/scala-2.12/apply-at-vdb-assembly-0.1.0-SNAPSHOT.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;fine-tune GraalVM with the following options and include the files that have been created in the previous step:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// build.sbt&lt;/span&gt;
  &lt;span class="n"&gt;graalVMNativeImageOptions&lt;/span&gt; &lt;span class="o"&gt;++=&lt;/span&gt; &lt;span class="nc"&gt;Seq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"--allow-incomplete-classpath"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-H:ResourceConfigurationFiles=../../configs/resource-config.json"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-H:ReflectionConfigurationFiles=../../configs/reflect-config.json"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-H:JNIConfigurationFiles=../../configs/jni-config.json"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"-H:DynamicProxyConfigurationFiles=../../configs/proxy-config.json"&lt;/span&gt;
  &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;build the native image with:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  sbt graalvm-native-image:packageBin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;run the executable file without the need of java
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ./target/graalvm-native-image/apply-at-vdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even without benchmarking, you notice that the startup time is way faster than with a traditional JAR-file and the application is up and running almost instantly.&lt;/p&gt;

&lt;p&gt;It is worth noting that the creation of a native image is a quite time-consuming process. For this project, it took between 1 and 2 minutes. This is, of course, something a CI/CD-Server like Jenkins would take care of but it has to be kept in mind. &lt;/p&gt;

&lt;p&gt;With a working native-image, it is time to dockerize.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Docker images
&lt;/h2&gt;

&lt;p&gt;In this section two Docker containers will be built. One, following the "normal"-java way and the other will be using the native-image to build a Docker-container without Java.&lt;/p&gt;

&lt;p&gt;Before getting started with native images, a regular JAR-file and Docker image for comparison can be built.&lt;/p&gt;

&lt;p&gt;With the &lt;a href="https://github.com/sbt/sbt-assembly"&gt;sbt-assembly&lt;/a&gt; plugin you can create JAR-files with all of its dependencies (fat JARs).&lt;br&gt;
&lt;code&gt;sbt assembly&lt;/code&gt; creates this &lt;code&gt;target/scala-2.12/apply-at-vdb-assembly-0.1.0-SNAPSHOT.jar&lt;/code&gt; which has a size of around 42MB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; sbt assembly 
 &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-lh&lt;/span&gt; target/scala-2.12/apply-at-vdb-assembly-0.1.0-SNAPSHOT.jar

  ...  ...   42M   target/scala-2.12/apply-at-vdb-assembly-0.1.0-SNAPSHOT.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This application can be run locally via &lt;code&gt;java -jar target/scala-2.12/apply-at-vdb-assembly-0.1.0-SNAPSHOT.jar&lt;/code&gt; with the prerequisite that Java is installed on that machine.&lt;/p&gt;

&lt;p&gt;Creating the Docker image for this JAR-file can be done manually, but luckily &lt;code&gt;sbt-native-package&lt;/code&gt; supports building regular Docker images out of the box, only the &lt;code&gt;DockerPlugin&lt;/code&gt; needs to be enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="c1"&gt;// build.sbt&lt;/span&gt;
&lt;span class="nf"&gt;enablePlugins&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DockerPlugin&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sbt docker:publishLocal&lt;/code&gt; creates the Docker image &lt;code&gt;apply-at-vdb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images | &lt;span class="nb"&gt;grep &lt;/span&gt;apply-at-vdb
  apply-at-vdb  0.1.0-SNAPSHOT      f488d4c06f28    555MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A whopping 555MB for a tiny app exposing one endpoint which JAR-file was only 42MB. But to run this JAR-file in a container, this container needs to ship with a JVM, and that's where the overhead lies.&lt;/p&gt;

&lt;p&gt;With that Docker image and JAR-file as a reference, we can now look into how the native-image operates together with Docker.&lt;/p&gt;

&lt;p&gt;GraalVM does not support cross-building, meaning an application cannot be expected to be built in a MacOS environment and run in a Linux environment. It has to be built and run on the same platform. With the help of Docker, the desired built environment can be provided.&lt;br&gt;
The &lt;code&gt;Dockerfile&lt;/code&gt; looks as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; oracle/graalvm-ce AS builder&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app/vdb&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;gu &lt;span class="nb"&gt;install &lt;/span&gt;native-image
&lt;span class="k"&gt;RUN &lt;/span&gt;curl https://bintray.com/sbt/rpm/rpm &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; bintray-sbt-rpm.repo &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mv &lt;/span&gt;bintray-sbt-rpm.repo /etc/yum.repos.d/ &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; sbt
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /app/vdb&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app/vdb&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;sbt &lt;span class="s2"&gt;"graalvm-native-image:packageBin"&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; oraclelinux:7-slim&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/vdb/target/graalvm-native-image/apply-at-vdb ./app/&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ./app/apply-at-vdb&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And can be run with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; native-apply-at-vdb &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Dockerfile describes to do the following:&lt;br&gt;
The first docker container, as the name implies, is the builder. As a base image the official &lt;a href="https://hub.docker.com/r/oracle/graalvm-ce"&gt;GraalVM image&lt;/a&gt; is used. &lt;/p&gt;

&lt;p&gt;This image needs two more things, GraalVM's native-image command, and sbt, and this is what the two follow-up rows are providing. Once that's done, the project is copied into this container and the native image is built from within sbt.&lt;/p&gt;

&lt;p&gt;The next steps bring the native executable into its own docker container.&lt;br&gt;
As a base image, we use an Oracle Linux image and from our builder-container, we copy the native executable to this new container. The last step is that the app gets run on container startup.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -p 8080:8080 -it native-apply-at-vdb&lt;/code&gt; starts the container and shows that everything is working just as before.&lt;/p&gt;

&lt;p&gt;But what about the image size? Let's have a look.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker images | grep apply-at-vdb
  native-apply-at-vdb       latest              17b559e78645        199MB
  apply-at-vdb          0.1.0-SNAPSHOT      f488d4c06f28        555MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is impressive! We created an app that is approx. 2.8 times smaller than our original app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;We learned how to set up a Scala project with GraalVM, what steps have to be taken to build a native image with GraalVM, and let it run inside a Docker container. We also received a good overview of what's possible with GraalVM and what's not.&lt;/p&gt;

&lt;p&gt;The initial start and setup of GraalVM with sbt is pretty easy and straightforward. Getting GraalVM to compile an sbt project is nice and simple. &lt;/p&gt;

&lt;p&gt;This Hackathon showed us that it is difficult and requires a lot of fine-tuning to integrate GraalVM into an existing project or product. At Vandebron we work with a complex stack of technologies including Spark, Kafka, and Akka which made it difficult to port the findings from this small toy service to one of our existing microservices. This made extensive troubleshooting in the Hackathon not possible.&lt;/p&gt;

&lt;p&gt;All in all, GraalVM allows you to give up some Java overhead and create significant smaller Docker images. Sadly, this comes at the cost of giving up dynamic linking and class loading. &lt;br&gt;
A silver lining is, that inside Scala's ecosystem this rarely a problem. Scala relies heavily on compile-time mechanisms for detecting bugs early and creating type-safe applications (read &lt;a href="https://blog.softwaremill.com/small-fast-docker-images-using-graalvms-native-image-99c0bc92e70b"&gt;here&lt;/a&gt; but also see e.g. &lt;a href="https://typelevel.org/scala/docs/phases.html"&gt;Scala's compiler phases&lt;/a&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources and Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.inner-product.com/posts/serverless-scala-services-with-graalvm/"&gt;Building Serverless Scala Services with GraalVM&lt;/a&gt; by Noel Welsh&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://blog.softwaremill.com/small-fast-docker-images-using-graalvms-native-image-99c0bc92e70b"&gt;Small &amp;amp; fast Docker images using GraalVM’s native-image&lt;/a&gt; by Adam Warski&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/rahasak/run-scala-applications-with-graalvm-and-docker-a1e67701e935"&gt;Run Scala applications with GraalVM and Docker&lt;/a&gt; by @itseranga&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/graalvm/getting-started-with-graalvm-for-scala-d0a006dec1d1"&gt;Getting Started with GraalVM and Scala&lt;/a&gt; by Oleg Šelajev&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/graalvm/updates-on-class-initialization-in-graalvm-native-image-generation-c61faca461f7"&gt;Updates on Class Initialization in GraalVM Native Image Generation&lt;/a&gt; by 
Christian Wimmer&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.graalvm.org/reference-manual/"&gt;GraalVM's Reference Manuals&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>graalvm</category>
      <category>scala</category>
      <category>sbt</category>
    </item>
  </channel>
</rss>
