Skip to content

Commit

Permalink
Implement OXM Marshaller and Unmarshaller (#139)
Browse files Browse the repository at this point in the history
Instead of using Jaxb2Marshaller provided by Spring to allow dependents
to use newer versions of spring-oxm (Spring 6 or greater)
where the Jaxb2Marshaller depends on Jakarta XML
Binding instead of javax XML Binding.

sdp-api-client uses specifically the Marshaller and Unmarshaller
interfaces from Spring OXM. These interfaces cleanly separates the
inputs and outputs from marshalling, and are compatible across Spring
major versions, in particular before and after version Spring Framework
v6.

sdp-commons has no dependency on Spring OXM.
  • Loading branch information
runeflobakk authored May 12, 2023
1 parent b69a4eb commit eab3859
Show file tree
Hide file tree
Showing 29 changed files with 517 additions and 218 deletions.
47 changes: 35 additions & 12 deletions api-client/src/main/java/no/digipost/api/MessageSender.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import no.digipost.api.representations.EbmsPullRequest;
import no.digipost.api.representations.KanBekreftesSomBehandletKvittering;
import no.digipost.api.representations.TransportKvittering;
import no.digipost.api.xml.JaxbMarshaller;
import no.digipost.api.xml.Marshalling;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequestInterceptor;
Expand All @@ -37,7 +38,8 @@
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.soap.SoapVersion;
Expand All @@ -46,6 +48,8 @@

import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
Expand Down Expand Up @@ -84,7 +88,7 @@ default EbmsApplikasjonsKvittering hentKvittering(EbmsPullRequest pullRequest) {

WebServiceTemplate getMeldingTemplate();

Jaxb2Marshaller getMarshaller();
JaxbMarshaller getMarshaller();

@FunctionalInterface
public static interface ClientInterceptorWrapper {
Expand All @@ -97,7 +101,7 @@ public static class Builder {

private static final Logger LOG = LoggerFactory.getLogger(MessageSender.Builder.class);

private static Jaxb2Marshaller defaultMarshaller;
private static JaxbMarshaller defaultMarshaller;
private final EbmsEndpointUriBuilder endpointUri;
private final EbmsAktoer databehandler;
private final EbmsAktoer tekniskMottaker;
Expand All @@ -106,7 +110,7 @@ public static class Builder {
private final List<InsertInterceptor> interceptorBefore = new ArrayList<InsertInterceptor>();
private final List<HttpRequestInterceptor> httpRequestInterceptors = new ArrayList<HttpRequestInterceptor>();
private final List<HttpResponseInterceptor> httpResponseInterceptors = new ArrayList<HttpResponseInterceptor>();
private Jaxb2Marshaller marshaller;
private JaxbMarshaller marshaller;
// Network config
private int maxTotal = DEFAULT_MAX_PER_ROUTE;
private int defaultMaxPerRoute = DEFAULT_MAX_PER_ROUTE;
Expand All @@ -130,7 +134,7 @@ private Builder(EbmsEndpointUriBuilder uri, EbmsAktoer databehandler, EbmsAktoer
}


protected static synchronized Jaxb2Marshaller getDefaultMarshaller() {
protected static synchronized JaxbMarshaller getDefaultMarshaller() {
if (defaultMarshaller == null) {
defaultMarshaller = Marshalling.getMarshallerSingleton();
}
Expand All @@ -148,11 +152,30 @@ private static void insertInterceptor(final List<ClientInterceptor> meldingInter
throw new IllegalArgumentException("Could not find interceptor of class " + insertInterceptor.clazz);
}

private static WebServiceTemplate createTemplate(SaajSoapMessageFactory factory, Jaxb2Marshaller marshaller, EbmsAktoer remoteParty,
private static WebServiceTemplate createTemplate(SaajSoapMessageFactory factory, JaxbMarshaller marshaller, EbmsAktoer remoteParty,
HttpComponentsMessageSender httpSender, ClientInterceptor[] interceptors) {

final class SpringOxmMarshaller implements Marshaller, Unmarshaller {
@Override
public boolean supports(Class<?> clazz) {
return true;
}

@Override
public Object unmarshal(Source source) {
return marshaller.unmarshal(source, Object.class);
}

@Override
public void marshal(Object graph, Result result) {
marshaller.marshal(graph, result);
}
}
SpringOxmMarshaller oxmMarshaller = new SpringOxmMarshaller();

EbmsContextAwareWebServiceTemplate template = new EbmsContextAwareWebServiceTemplate(factory, remoteParty);
template.setMarshaller(marshaller);
template.setUnmarshaller(marshaller);
template.setMarshaller(oxmMarshaller);
template.setUnmarshaller(oxmMarshaller);
template.setFaultMessageResolver(new MessageSenderFaultMessageResolver(marshaller));
template.setMessageSender(httpSender);
template.setInterceptors(interceptors);
Expand All @@ -169,7 +192,7 @@ public Builder withValidateAfterInactivity(final Duration validateAfterInactivit
return this;
}

public Builder withMarshaller(final Jaxb2Marshaller marshaller) {
public Builder withMarshaller(JaxbMarshaller marshaller) {
this.marshaller = marshaller;
return this;
}
Expand Down Expand Up @@ -330,15 +353,15 @@ public InsertInterceptor(final Class<?> clazz, final ClientInterceptor intercept
static class DefaultMessageSender implements MessageSender {

private static final Logger LOG = LoggerFactory.getLogger(DefaultMessageSender.class);
private final Jaxb2Marshaller marshaller;
private final JaxbMarshaller marshaller;
private final EbmsEndpointUriBuilder uri;
private WebServiceTemplate meldingTemplate;
private EbmsAktoer databehandler;
private EbmsAktoer tekniskMottaker;
private SdpMeldingSigner signer;


protected DefaultMessageSender(final EbmsEndpointUriBuilder uri, final Jaxb2Marshaller marshaller) {
protected DefaultMessageSender(EbmsEndpointUriBuilder uri, JaxbMarshaller marshaller) {
if (marshaller == null) {
throw new AssertionError("marshaller kan ikke være null");
}
Expand Down Expand Up @@ -377,7 +400,7 @@ public void send(final EbmsApplikasjonsKvittering appKvittering) {
}

@Override
public Jaxb2Marshaller getMarshaller() {
public JaxbMarshaller getMarshaller() {
return marshaller;
}

Expand Down
27 changes: 5 additions & 22 deletions api-client/src/main/java/no/digipost/api/SdpMeldingSigner.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,18 @@

import no.digipost.api.interceptors.KeyStoreInfo;
import no.digipost.api.xml.Constants;
import no.digipost.api.xml.JaxbMarshaller;
import no.digipost.api.xml.Marshalling;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import no.digipost.org.unece.cefact.namespaces.standardbusinessdocumentheader.StandardBusinessDocument;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureException;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
Expand All @@ -24,24 +22,21 @@
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.transform.dom.DOMResult;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.X509Certificate;
import java.util.Collections;

public class SdpMeldingSigner {
private final Jaxb2Marshaller marshaller;
private final JaxbMarshaller marshaller;
private final KeyStoreInfo keystoreInfo;

public SdpMeldingSigner(final KeyStoreInfo keystoreInfo, final Jaxb2Marshaller marshaller) {
public SdpMeldingSigner(KeyStoreInfo keystoreInfo, JaxbMarshaller marshaller) {
this.keystoreInfo = keystoreInfo;
this.marshaller = marshaller;
}

public Document sign(final StandardBusinessDocument sbd) {
public Document sign(StandardBusinessDocument sbd) {
try {
PrivateKey privateKey = keystoreInfo.getPrivateKey();
X509Certificate certificate = keystoreInfo.getCertificate();
Expand Down Expand Up @@ -71,18 +66,6 @@ public Document sign(final StandardBusinessDocument sbd) {

doc.normalizeDocument();
return doc;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (UnrecoverableKeyException e) {
throw new RuntimeException(e);
} catch (XMLSignatureException e) {
throw new RuntimeException(e);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
} catch (KeyStoreException e) {
throw new RuntimeException(e);
} catch (MarshalException e) {
throw new RuntimeException(e);
} catch (Exception e) {
throw new RuntimeException(e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package no.digipost.api.exceptions;

import no.digipost.api.xml.JaxbMarshaller;
import no.digipost.api.xml.Marshalling;
import no.digipost.org.oasis_open.docs.ebxml_msg.ebms.v3_0.ns.core._200704.Error;
import no.digipost.org.oasis_open.docs.ebxml_msg.ebms.v3_0.ns.core._200704.Messaging;
import no.digipost.org.oasis_open.docs.ebxml_msg.ebms.v3_0.ns.core._200704.SignalMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.FaultMessageResolver;
import org.springframework.ws.soap.SoapHeaderElement;
Expand All @@ -24,9 +24,9 @@ public class MessageSenderFaultMessageResolver implements FaultMessageResolver {

private static final Logger LOG = LoggerFactory.getLogger(MessageSenderFaultMessageResolver.class);

private Jaxb2Marshaller marshaller;
private JaxbMarshaller marshaller;

public MessageSenderFaultMessageResolver(Jaxb2Marshaller marshaller) {
public MessageSenderFaultMessageResolver(JaxbMarshaller marshaller) {
this.marshaller = marshaller;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,26 @@

import no.digipost.api.representations.EbmsAktoer;
import no.digipost.api.representations.EbmsApplikasjonsKvittering;
import no.digipost.api.xml.JaxbMarshaller;
import no.digipost.api.xml.Marshalling;
import no.digipost.org.oasis_open.docs.ebxml_msg.ebms.v3_0.ns.core._200704.PartyInfo;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import no.digipost.org.unece.cefact.namespaces.standardbusinessdocumentheader.StandardBusinessDocument;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageExtractor;
import org.springframework.ws.soap.SoapBody;
import org.springframework.ws.soap.SoapMessage;
import no.digipost.org.unece.cefact.namespaces.standardbusinessdocumentheader.StandardBusinessDocument;

import javax.xml.transform.TransformerException;

import java.io.IOException;

public class ApplikasjonsKvitteringReceiver extends EbmsContextAware implements WebServiceMessageExtractor<EbmsApplikasjonsKvittering> {

private static final String NO_MESSAGE_AVAILABLE_FROM_MPC_ERROR_CODE = "EBMS:0006";

private final Jaxb2Marshaller jaxb2Marshaller;
private final JaxbMarshaller jaxb2Marshaller;

public ApplikasjonsKvitteringReceiver(final Jaxb2Marshaller jaxb2Marshaller) {
public ApplikasjonsKvitteringReceiver(JaxbMarshaller jaxb2Marshaller) {
this.jaxb2Marshaller = jaxb2Marshaller;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,29 @@

import no.digipost.api.interceptors.steps.AddReferencesStep;
import no.digipost.api.representations.KanBekreftesSomBehandletKvittering;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import no.digipost.api.xml.JaxbMarshaller;
import no.digipost.org.w3.xmldsig.Reference;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import no.digipost.org.w3.xmldsig.Reference;

import javax.xml.transform.TransformerException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class BekreftelseSender extends EbmsContextAware implements WebServiceMessageCallback {

private final KanBekreftesSomBehandletKvittering kanBekreftesSomBehandletKvittering;
private final Jaxb2Marshaller jaxb2Marshaller;
private final JaxbMarshaller jaxb2Marshaller;

public BekreftelseSender(final KanBekreftesSomBehandletKvittering kanBekreftesSomBehandletKvittering, final Jaxb2Marshaller jaxb2Marshaller) {
public BekreftelseSender(KanBekreftesSomBehandletKvittering kanBekreftesSomBehandletKvittering, JaxbMarshaller jaxb2Marshaller) {
this.kanBekreftesSomBehandletKvittering = kanBekreftesSomBehandletKvittering;
this.jaxb2Marshaller = jaxb2Marshaller;
}

@Override
public void doWithMessage(final WebServiceMessage message) throws IOException, TransformerException {
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
List<Reference> references = new ArrayList<Reference>();
references.add(kanBekreftesSomBehandletKvittering.getReferanseTilMeldingSomKvitteres().getUnmarshalled());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,43 @@
import no.digipost.api.representations.EbmsAktoer;
import no.digipost.api.representations.EbmsForsendelse;
import no.digipost.api.representations.Mpc;
import no.digipost.api.xml.JaxbMarshaller;
import no.digipost.api.xml.Marshalling;
import no.digipost.api.xml.TransformerUtil;
import no.digipost.org.unece.cefact.namespaces.standardbusinessdocumentheader.StandardBusinessDocument;
import no.digipost.org.w3.xmldsig.DigestMethod;
import no.digipost.org.w3.xmldsig.Reference;
import no.digipost.xsd.types.DigitalPostformidling;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.soap.SoapMessage;
import no.digipost.org.unece.cefact.namespaces.standardbusinessdocumentheader.StandardBusinessDocument;
import no.digipost.org.w3.xmldsig.DigestMethod;
import no.digipost.org.w3.xmldsig.Reference;
import org.w3c.dom.Document;

import javax.activation.DataHandler;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamSource;

import java.io.IOException;
import java.util.UUID;

public class ForsendelseSender extends EbmsContextAware implements WebServiceMessageCallback {

private final StandardBusinessDocument doc;
private final EbmsForsendelse forsendelse;
private final Jaxb2Marshaller marshaller;
private final JaxbMarshaller marshaller;
private final EbmsAktoer databehandler;
private final EbmsAktoer tekniskMottaker;
private final DigitalPostformidling digitalPostformidling;
private final SdpMeldingSigner signer;

public ForsendelseSender(final SdpMeldingSigner signer, final EbmsAktoer databehandler, final EbmsAktoer tekniskMottaker, final EbmsForsendelse forsendelse, final Jaxb2Marshaller marshaller) {
public ForsendelseSender(final SdpMeldingSigner signer, final EbmsAktoer databehandler, final EbmsAktoer tekniskMottaker, final EbmsForsendelse forsendelse, final JaxbMarshaller marshaller) {
this.signer = signer;
this.databehandler = databehandler;
this.tekniskMottaker = tekniskMottaker;
doc = forsendelse.doc;
this.doc = forsendelse.doc;
this.forsendelse = forsendelse;
this.marshaller = marshaller;
digitalPostformidling = (DigitalPostformidling) doc.getAny();
this.digitalPostformidling = (DigitalPostformidling) doc.getAny();
}

public static void lagFingeravtrykk(final EbmsForsendelse forsendelse, final DigitalPostformidling digitalPostformidling) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,28 @@
import no.digipost.api.representations.EbmsApplikasjonsKvittering;
import no.digipost.api.representations.Mpc;
import no.digipost.api.representations.SimpleStandardBusinessDocument;
import no.digipost.api.xml.JaxbMarshaller;
import no.digipost.api.xml.Marshalling;
import no.digipost.api.xml.TransformerUtil;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.soap.SoapMessage;
import org.w3c.dom.Document;

import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamSource;

import java.io.IOException;

public class KvitteringSender extends EbmsContextAware implements WebServiceMessageCallback {

private final EbmsApplikasjonsKvittering appKvittering;
private final Jaxb2Marshaller marshaller;
private final JaxbMarshaller marshaller;
private final EbmsAktoer databehandler;
private final EbmsAktoer tekniskMottaker;
private final SdpMeldingSigner signer;

public KvitteringSender(final SdpMeldingSigner signer, final EbmsAktoer databehandler, final EbmsAktoer tekniskMottaker, final EbmsApplikasjonsKvittering appKvittering, final Jaxb2Marshaller marshaller) {
public KvitteringSender(SdpMeldingSigner signer, EbmsAktoer databehandler, EbmsAktoer tekniskMottaker, EbmsApplikasjonsKvittering appKvittering, JaxbMarshaller marshaller) {
this.signer = signer;
this.databehandler = databehandler;
this.tekniskMottaker = tekniskMottaker;
Expand All @@ -35,7 +36,7 @@ public KvitteringSender(final SdpMeldingSigner signer, final EbmsAktoer databeha
}

@Override
public void doWithMessage(final WebServiceMessage message) throws IOException, TransformerException {
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
SoapMessage soapMessage = (SoapMessage) message;
SimpleStandardBusinessDocument simple = new SimpleStandardBusinessDocument(appKvittering.sbd);
if (appKvittering.sbdStream != null) {
Expand All @@ -48,8 +49,8 @@ public void doWithMessage(final WebServiceMessage message) throws IOException, T
}

Mpc mpc = new Mpc(appKvittering.prioritet, appKvittering.mpcId);
ebmsContext.addRequestStep(new AddUserMessageStep(mpc, appKvittering.messageId, appKvittering.action, null, appKvittering.sbd, databehandler, tekniskMottaker
, marshaller));
ebmsContext.addRequestStep(new AddUserMessageStep(
mpc, appKvittering.messageId, appKvittering.action, null, appKvittering.sbd, databehandler, tekniskMottaker, marshaller));
}

}
Loading

0 comments on commit eab3859

Please sign in to comment.