title: Sign JAX-WS SOAP request
body: <p>I would like to write a JAX-WS web service that signs my SOAP messages using the <a href="http://www.w3.org/TR/xmldsig-core/">http://www.w3.org/TR/xmldsig-core/</a> recommendation.</p>
  
  <p>With what I found on the internet I wrote a JAX-WS handler (<code>SOAPHandler&lt;SOAPMessageContext&gt;</code>) that manages to change a copy of the SOAP request:</p>
  
  <pre><code>@Override
  public boolean handleMessage(SOAPMessageContext smc) {
      Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
      SOAPMessage message = smc.getMessage();
  
      if (outboundProperty) {
          try {
              SOAPPart soapPart = message.getSOAPPart();
              SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
  
              Source source = soapPart.getContent();
  
              Node root = null;
              Document doc22 = null;
              if (source instanceof DOMSource) {
                  root = ((DOMSource) source).getNode();
              } else if (source instanceof SAXSource) {
                  InputSource inSource = ((SAXSource) source).getInputSource();
                  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                  dbf.setNamespaceAware(true);
                  DocumentBuilder db = null;
  
                  db = dbf.newDocumentBuilder();
  
                  doc22 = db.parse(inSource);
                  root = (Node) doc22.getDocumentElement();
              }
  
              XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
  
              Reference ref = fac.newReference("", fac.newDigestMethod(DigestMethod.SHA1, null),
                      Collections.singletonList(fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)),
                      null, null);
  
              SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
                      (C14NMethodParameterSpec) null),
                      fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
                      Collections.singletonList(ref));
  
              // Load the KeyStore and get the signing key and certificate.
              KeyStore ks = KeyStore.getInstance("JKS");
              ks.load(new FileInputStream("client_keystore.jks"), "changeit".toCharArray());
              KeyStore.PrivateKeyEntry keyEntry =
                      (KeyStore.PrivateKeyEntry) ks.getEntry("client", new KeyStore.PasswordProtection("changeit".toCharArray()));
              X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
              // Create the KeyInfo containing the X509Data.
              KeyInfoFactory kif2 = fac.getKeyInfoFactory();
              List x509Content = new ArrayList();
              x509Content.add(cert.getSubjectX500Principal().getName());
              x509Content.add(cert);
              X509Data xd = kif2.newX509Data(x509Content);
              KeyInfo ki = kif2.newKeyInfo(Collections.singletonList(xd));
  
              Element header = getFirstChildElement(root/*.getDocumentElement()*/);
              DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), header /*doc.getDocumentElement()*/);
  
              XMLSignature signature = fac.newXMLSignature(si, ki);
  
              signature.sign(dsc);
  
              //TODO: change this to update the SOAP message, not write it to disks
              OutputStream os = new FileOutputStream("out.xml");
              TransformerFactory tf = TransformerFactory.newInstance();
              Transformer trans = tf.newTransformer();
              trans.transform(new DOMSource(root), new StreamResult(os));
  
          } catch (Exception ex) {
              System.out.println(ex);
          }
      }
  
      return true;
  }
  </code></pre>
  
  <p>But I can't figure out how to update the SOAP request?</p>