From e6a508faaabbd3aec42892036a43b77b1908f0de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simen=20St=C3=B8a?= Date: Fri, 3 Feb 2023 13:20:39 +0100 Subject: [PATCH 1/9] Remove Spring OXM Using JDK API for JAXB marshalling instead of Spring Jaxb2Marshaller --- jaxb/pom.xml | 23 -- .../signature/jaxb/JaxbMarshaller.java | 207 ++++++++++++++++++ .../jaxb/SignatureMarshalException.java | 42 ++++ .../signature/jaxb/SignatureMarshalling.java | 3 - .../jaxb/adapter/DateTimeXmlAdapter.java | 2 +- .../jaxb/spring/SignatureJaxb2Marshaller.java | 148 ------------- .../signature/jaxb/spring/SpringUtils.java | 37 ---- .../signature/xsd/SignatureApiSchemas.java | 4 +- ...allerTest.java => JaxbMarshallerTest.java} | 23 +- .../jaxb/spring/MarshallingMatchers.java | 24 +- ...e_job_response_with_unexpected_element.xml | 2 +- 11 files changed, 277 insertions(+), 238 deletions(-) create mode 100644 jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java create mode 100644 jaxb/src/main/java/no/digipost/signature/jaxb/SignatureMarshalException.java delete mode 100644 jaxb/src/main/java/no/digipost/signature/jaxb/spring/SignatureJaxb2Marshaller.java delete mode 100644 jaxb/src/main/java/no/digipost/signature/jaxb/spring/SpringUtils.java rename jaxb/src/test/java/no/digipost/signature/jaxb/spring/{SignatureJaxb2MarshallerTest.java => JaxbMarshallerTest.java} (89%) diff --git a/jaxb/pom.xml b/jaxb/pom.xml index ebd9ed52..b6385488 100644 --- a/jaxb/pom.xml +++ b/jaxb/pom.xml @@ -26,13 +26,6 @@ pom import - - org.springframework - spring-framework-bom - 5.3.13 - pom - import - @@ -60,16 +53,6 @@ runtime true - - org.springframework - spring-core - true - - - org.springframework - spring-oxm - true - org.junit.jupiter junit-jupiter-api @@ -128,12 +111,6 @@ 1.7.32 test - - org.springframework.ws - spring-xml - 3.1.1 - test - diff --git a/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java b/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java new file mode 100644 index 00000000..21bea8a1 --- /dev/null +++ b/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java @@ -0,0 +1,207 @@ +/* + * Copyright (C) Posten Norge AS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package no.digipost.signature.jaxb; + +import no.digipost.signature.xsd.SignatureApiSchemas; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.Source; +import javax.xml.transform.sax.SAXSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.net.URL; +import java.util.Collection; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; + +import static java.util.Objects.requireNonNull; +import static java.util.stream.Collectors.joining; + +/** + * @see JaxbMarshaller.ForResponsesOfAllApis + * @see JaxbMarshaller.ForRequestsOfAllApis + */ +public abstract class JaxbMarshaller { + + /** + * Marshaller for creating requests for both the Direct and Portal API. + * This marshaller will validate if the XML generated from marshalled Java objects + * adheres to the API schemas. + */ + static class ForRequestsOfAllApis extends JaxbMarshaller { + + public static JaxbMarshaller singleton() { + return SingletonHolder.instance; + } + + private static final class SingletonHolder { + private static final JaxbMarshaller instance = new JaxbMarshaller.ForRequestsOfAllApis(); + } + + public ForRequestsOfAllApis() { + super(SignatureMarshalling.allApiRequestClasses(), SignatureApiSchemas.DIRECT_AND_PORTAL_API); + } + } + + + /** + * Marshaller (unmarshaller) for reading responses from both the Direct and Portal API. + * This marshaller does not validate the XML before attempting to unmarshal it to Java objects. + */ + public static class ForResponsesOfAllApis extends JaxbMarshaller { + + public static JaxbMarshaller singleton() { + return SingletonHolder.instance; + } + + private static final class SingletonHolder { + private static final JaxbMarshaller instance = new JaxbMarshaller.ForResponsesOfAllApis(); + } + + public ForResponsesOfAllApis() { + super(SignatureMarshalling.allApiResponseClasses()); + } + } + + + + /** + * Marshaller for both the Direct and Portal API. + *

+ * This marshaller is intended only to be used internally by Posten signering, as both + * requests and responses are validated against schemas. A 3rd party client should not + * validate responses from the API. + * + * + * @see JaxbMarshaller.ForResponsesOfAllApis + * @see JaxbMarshaller.ForRequestsOfAllApis + */ + public static class ForAllApis extends JaxbMarshaller { + + public static JaxbMarshaller singleton() { + return SingletonHolder.instance; + } + + private static final class SingletonHolder { + private static final JaxbMarshaller instance = new JaxbMarshaller.ForAllApis(); + } + + public ForAllApis() { + super(SignatureMarshalling.allApiClasses(), SignatureApiSchemas.DIRECT_AND_PORTAL_API); + } + } + + private static InputSource createInputSource(String resource) { + URL resourceUrl = requireNonNull(JaxbMarshaller.class.getResource(resource), resource); + try (InputStream inputStream = resourceUrl.openStream()) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + final int bufLen = 1024; + byte[] buf = new byte[bufLen]; + int readLen; + while ((readLen = inputStream.read(buf, 0, bufLen)) != -1) + outputStream.write(buf, 0, readLen); + + InputSource source = new InputSource(new ByteArrayInputStream(outputStream.toByteArray())); + source.setSystemId(resourceUrl.toString()); + return source; + } catch (IOException e) { + throw new UncheckedIOException( + "Unable to resolve " + resource + " from " + resourceUrl + ", " + + "because " + e.getClass().getSimpleName() + " '" + e.getMessage() + "'", e); + } + } + + private static Schema createSchema(Collection resources) { + try { + SAXParserFactory parserFactory = SAXParserFactory.newInstance(); + parserFactory.setNamespaceAware(true); + parserFactory.setFeature("http://xml.org/sax/features/namespace-prefixes", true); + + SAXParser saxParser = parserFactory.newSAXParser(); + XMLReader xmlReader = saxParser.getXMLReader(); + Source[] schemaSources = resources.stream() + .map(resource -> new SAXSource(xmlReader, createInputSource(resource))) + .toArray(Source[]::new); + + SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + Schema schema = schemaFactory.newSchema(schemaSources); + return schema; + } catch (SAXException | ParserConfigurationException e) { + throw new RuntimeException("Could not create schema from resources [" + String.join(", ", resources) + "]", e); + } + } + + private static JAXBContext initContext(Collection> classes) { + Class[] classesToBeBound = classes.toArray(new Class[classes.size()]); + try { + return JAXBContext.newInstance(classesToBeBound); + } catch (JAXBException e) { + throw new RuntimeException("Could not create JAXBContext for classes [" + Stream.of(classesToBeBound).map(Class::getSimpleName).collect(joining(",")) + "]" , e); + } + } + + private final JAXBContext jaxbContext; + private final Optional schema; + + JaxbMarshaller(Set> classes, Set schemaResources) { + this.jaxbContext = initContext(classes); + this.schema = Optional.ofNullable(schemaResources).filter(s -> !s.isEmpty()).map(JaxbMarshaller::createSchema); + } + + JaxbMarshaller(Set> classes) { + this(classes, null); + } + + public void marshal(Object object, OutputStream outputStream){ + try { + Marshaller marshaller = jaxbContext.createMarshaller(); + schema.ifPresent(marshaller::setSchema); + marshaller.marshal(object, outputStream); + } catch (Exception e) { + throw new SignatureMarshalException("Failed marshalling " + (object != null ? object.getClass().getName() : "null") + " to XML", e); + } + } + + public T unmarshal(InputStream inputStream, Class type){ + try { + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + schema.ifPresent(unmarshaller::setSchema); + return type.cast(unmarshaller.unmarshal(inputStream)); + } catch (Exception e) { + throw new SignatureMarshalException("Failed unmarshalling XML to " + type.getName(), e); + } + } + +} diff --git a/jaxb/src/main/java/no/digipost/signature/jaxb/SignatureMarshalException.java b/jaxb/src/main/java/no/digipost/signature/jaxb/SignatureMarshalException.java new file mode 100644 index 00000000..698deae9 --- /dev/null +++ b/jaxb/src/main/java/no/digipost/signature/jaxb/SignatureMarshalException.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) Posten Norge AS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package no.digipost.signature.jaxb; + +import java.util.stream.Stream; + +import static java.util.stream.Collectors.joining; + +public class SignatureMarshalException extends RuntimeException { + + public SignatureMarshalException(String message, Throwable cause) { + super(message + (cause != null ? ", because " + messageIncludingCauses(cause) : ""), cause); + } + + private static String messageIncludingCauses(Throwable throwable) { + return causalChainOf(throwable) + .map(e -> e.getClass().getSimpleName() + ": '" + e.getMessage() + "'") + .collect(joining(", caused by ")); + } + + private static Stream causalChainOf(Throwable t) { + Stream.Builder causes = Stream.builder(); + for (Throwable cause = t; cause != null; cause = cause.getCause()) { + causes.add(cause); + } + return causes.build(); + } + +} diff --git a/jaxb/src/main/java/no/digipost/signature/jaxb/SignatureMarshalling.java b/jaxb/src/main/java/no/digipost/signature/jaxb/SignatureMarshalling.java index 73996fd5..1a7d77eb 100644 --- a/jaxb/src/main/java/no/digipost/signature/jaxb/SignatureMarshalling.java +++ b/jaxb/src/main/java/no/digipost/signature/jaxb/SignatureMarshalling.java @@ -28,7 +28,6 @@ import no.digipost.signature.api.xml.XMLPortalSignatureJobStatusChangeResponse; import no.digipost.signature.api.xml.thirdparty.asice.XAdESSignatures; import no.digipost.signature.api.xml.thirdparty.xades.QualifyingProperties; -import no.digipost.signature.jaxb.spring.SignatureJaxb2Marshaller; import java.util.Collection; import java.util.Collections; @@ -42,8 +41,6 @@ * Different sets of classes to be bound by a {@link javax.xml.bind.JAXBContext JAXB context} in order to * create marshallers and unmarshallers. All the sets are immutable. *

- * If you use Spring, there are ready preconfigured {@link org.springframework.oxm.jaxb.Jaxb2Marshaller}s - * available in {@link SignatureJaxb2Marshaller}. */ public final class SignatureMarshalling { diff --git a/jaxb/src/main/java/no/digipost/signature/jaxb/adapter/DateTimeXmlAdapter.java b/jaxb/src/main/java/no/digipost/signature/jaxb/adapter/DateTimeXmlAdapter.java index ed892922..3635e83d 100644 --- a/jaxb/src/main/java/no/digipost/signature/jaxb/adapter/DateTimeXmlAdapter.java +++ b/jaxb/src/main/java/no/digipost/signature/jaxb/adapter/DateTimeXmlAdapter.java @@ -42,4 +42,4 @@ public String marshal(final ZonedDateTime value) { return DatatypeConverter.printDateTime(GregorianCalendar.from(value)); } -} \ No newline at end of file +} diff --git a/jaxb/src/main/java/no/digipost/signature/jaxb/spring/SignatureJaxb2Marshaller.java b/jaxb/src/main/java/no/digipost/signature/jaxb/spring/SignatureJaxb2Marshaller.java deleted file mode 100644 index 3a0d532f..00000000 --- a/jaxb/src/main/java/no/digipost/signature/jaxb/spring/SignatureJaxb2Marshaller.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) Posten Norge AS - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package no.digipost.signature.jaxb.spring; - -import no.digipost.signature.jaxb.SignatureMarshalling; -import no.digipost.signature.xsd.SignatureApiSchemas; -import org.springframework.core.io.Resource; -import org.springframework.oxm.jaxb.Jaxb2Marshaller; - -import java.util.Collections; -import java.util.Set; - -import static no.digipost.signature.jaxb.spring.SpringUtils.asClassPathResources; - -/** - * Various Spring {@link Jaxb2Marshaller}s which are configured for marshalling and/or unmarshalling - * request and response messages for the Posten signering API. To use this marshaller, make sure you have both - * Spring OXM and - * Posten signering - API Schema - * on your classpath. - *

- * Instances of SignatureJaxb2Marshaller behaves as expected when managed by a Spring DI container, following the pattern of an - * {@link org.springframework.beans.factory.InitializingBean InitializingBean}, meaning that {@link #afterPropertiesSet()} will properly - * initialize after it is constructed and configured. - *

- * Using one of the various static factory methods for retrieving singleton instances does not require any call to - * {@link #afterPropertiesSet()}. Each factory method will ensure that the marshaller is instantiated only on the first invocation of this method, - * and repeated invokations will always return the same instance, which will be ready to use immediately. - * - * @see SignatureJaxb2Marshaller.ForResponsesOfAllApis - * @see SignatureJaxb2Marshaller.ForRequestsOfAllApis - */ -public abstract class SignatureJaxb2Marshaller extends Jaxb2Marshaller { - - - - /** - * Marshaller for creating requests for both the Direct and Portal API. - * This marshaller will validate if the XML generated from marshalled Java objects - * adheres to the API schemas. - */ - public static class ForRequestsOfAllApis extends SignatureJaxb2Marshaller { - - public static Jaxb2Marshaller singleton() { - return SingletonHolder.instance; - } - - private static final class SingletonHolder { - private static final SignatureJaxb2Marshaller instance = new SignatureJaxb2Marshaller.ForRequestsOfAllApis().triggerBeanInitialized(); - } - - public ForRequestsOfAllApis() { - super(SignatureMarshalling.allApiRequestClasses(), asClassPathResources(SignatureApiSchemas.DIRECT_AND_PORTAL_API)); - } - } - - - /** - * Marshaller (unmarshaller) for reading responses from both the Direct and Portal API. - * This marshaller does not validate the XML before attempting to unmarshal it to Java objects. - */ - public static class ForResponsesOfAllApis extends SignatureJaxb2Marshaller { - - public static Jaxb2Marshaller singleton() { - return SingletonHolder.instance; - } - - private static final class SingletonHolder { - private static final SignatureJaxb2Marshaller instance = new SignatureJaxb2Marshaller.ForResponsesOfAllApis().triggerBeanInitialized(); - } - - public ForResponsesOfAllApis() { - super(SignatureMarshalling.allApiResponseClasses(), Collections.emptySet()); - } - } - - - - /** - * Marshaller for both the Direct and Portal API. - *

- * This marshaller is intended only to be used internally by Posten signering, as both - * requests and responses are validated against schemas. A 3rd party client should not - * validate responses from the API. - * - * - * - * @see SignatureJaxb2Marshaller.ForResponsesOfAllApis - * @see SignatureJaxb2Marshaller.ForRequestsOfAllApis - */ - public static class ForAllApis extends SignatureJaxb2Marshaller { - - public static Jaxb2Marshaller singleton() { - return SingletonHolder.instance; - } - - private static final class SingletonHolder { - private static final SignatureJaxb2Marshaller instance = new SignatureJaxb2Marshaller.ForAllApis().triggerBeanInitialized(); - } - - public ForAllApis() { - super(SignatureMarshalling.allApiClasses(), asClassPathResources(SignatureApiSchemas.DIRECT_AND_PORTAL_API)); - } - } - - - - - private final Set schemas; - - protected SignatureJaxb2Marshaller(Set> classesToBeBound, Set schemasForValidation) { - this.schemas = schemasForValidation; - setClassesToBeBound(classesToBeBound.toArray(new Class[classesToBeBound.size()])); - if (schemas != null && !schemas.isEmpty()) { - setSchemas(schemas.toArray(new Resource[schemas.size()])); - } - } - - @Override - public void afterPropertiesSet() { - try { - super.afterPropertiesSet(); - } catch (Exception e) { - throw new IllegalStateException("Initializing " + Jaxb2Marshaller.class.getSimpleName() + " failed because " + - e.getClass().getSimpleName() + ": '" + e.getMessage() + "'. " + - "ClassesToBeBound=" + getClassesToBeBound() + ", schemas=" + schemas + ". " + - "Do you have both Spring OXM and the signature-api-specification on your classpath?"); - } - } - - SignatureJaxb2Marshaller triggerBeanInitialized() { - afterPropertiesSet(); - return this; - } -} \ No newline at end of file diff --git a/jaxb/src/main/java/no/digipost/signature/jaxb/spring/SpringUtils.java b/jaxb/src/main/java/no/digipost/signature/jaxb/spring/SpringUtils.java deleted file mode 100644 index 87769668..00000000 --- a/jaxb/src/main/java/no/digipost/signature/jaxb/spring/SpringUtils.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) Posten Norge AS - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package no.digipost.signature.jaxb.spring; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; - -import java.util.LinkedHashSet; -import java.util.Set; - -import static java.util.Collections.unmodifiableSet; - -final class SpringUtils { - - static Set asClassPathResources(Iterable schemaResourceNames) { - Set schemas = new LinkedHashSet<>(); - for (String schemaResourceName : schemaResourceNames) { - schemas.add(new ClassPathResource(schemaResourceName)); - } - return unmodifiableSet(schemas); - } - - private SpringUtils() { } -} diff --git a/jaxb/src/main/java/no/digipost/signature/xsd/SignatureApiSchemas.java b/jaxb/src/main/java/no/digipost/signature/xsd/SignatureApiSchemas.java index 244ad618..584892d6 100644 --- a/jaxb/src/main/java/no/digipost/signature/xsd/SignatureApiSchemas.java +++ b/jaxb/src/main/java/no/digipost/signature/xsd/SignatureApiSchemas.java @@ -34,7 +34,7 @@ public final class SignatureApiSchemas { public static final String DIRECT_AND_PORTAL_SCHEMA = "/direct-and-portal.xsd"; public static final String DIRECT_ONLY_SCHEMA = "/direct.xsd"; - public static final String PORTAL_ONLY_SCHEMA = "/direct.xsd"; + public static final String PORTAL_ONLY_SCHEMA = "/portal.xsd"; public static final String XMLDSIG_SCHEMA = "/thirdparty/xmldsig-core-schema.xsd"; public static final String XADES_SCHEMA = "/thirdparty/XAdES.xsd"; @@ -53,6 +53,6 @@ public final class SignatureApiSchemas { /** * The schemas for the Portal API */ - public static final Set PORTAL_API = unmodifiableSet(new LinkedHashSet<>(asList(DIRECT_ONLY_SCHEMA, XMLDSIG_SCHEMA, XADES_SCHEMA, ASICE_SCHEMA))); + public static final Set PORTAL_API = unmodifiableSet(new LinkedHashSet<>(asList(PORTAL_ONLY_SCHEMA, XMLDSIG_SCHEMA, XADES_SCHEMA, ASICE_SCHEMA))); } diff --git a/jaxb/src/test/java/no/digipost/signature/jaxb/spring/SignatureJaxb2MarshallerTest.java b/jaxb/src/test/java/no/digipost/signature/jaxb/spring/JaxbMarshallerTest.java similarity index 89% rename from jaxb/src/test/java/no/digipost/signature/jaxb/spring/SignatureJaxb2MarshallerTest.java rename to jaxb/src/test/java/no/digipost/signature/jaxb/spring/JaxbMarshallerTest.java index 1f519682..20d8650b 100644 --- a/jaxb/src/test/java/no/digipost/signature/jaxb/spring/SignatureJaxb2MarshallerTest.java +++ b/jaxb/src/test/java/no/digipost/signature/jaxb/spring/JaxbMarshallerTest.java @@ -33,10 +33,9 @@ import no.digipost.signature.api.xml.XMLPortalSigner; import no.digipost.signature.api.xml.XMLSender; import no.digipost.signature.api.xml.XMLSignerStatus; +import no.digipost.signature.jaxb.JaxbMarshaller; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.oxm.MarshallingFailureException; -import org.springframework.oxm.jaxb.Jaxb2Marshaller; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; @@ -63,9 +62,9 @@ import static org.hamcrest.Matchers.sameInstance; import static org.junit.jupiter.api.Assertions.assertThrows; -class SignatureJaxb2MarshallerTest { +class JaxbMarshallerTest { - private static final Jaxb2Marshaller marshaller = SignatureJaxb2Marshaller.ForAllApis.singleton(); + private static final JaxbMarshaller marshaller = JaxbMarshaller.ForAllApis.singleton(); private static final MarshallingMatchers marshalling = new MarshallingMatchers(marshaller); @@ -113,8 +112,8 @@ void invalid_manifest_causes_exceptions() { asList(directSigner), sender, null, "Title", null, asList(directDocument), FOUR, PERSONAL_IDENTIFICATION_NUMBER_AND_NAME); - MarshallingFailureException marshallingFailure = - assertThrows(MarshallingFailureException.class, () -> marshaller.marshal(directManifest, new StreamResult(new ByteArrayOutputStream()))); + RuntimeException marshallingFailure = + assertThrows(RuntimeException.class, () -> marshaller.marshal(directManifest, new StreamResult(new ByteArrayOutputStream()).getOutputStream())); assertThat(marshallingFailure, where(Exception::getMessage, allOf(containsString("href"), containsString("must appear")))); } @@ -128,8 +127,8 @@ void invalid_signature_job_request_causes_exceptions() { XMLDirectSignatureJobRequest signatureJobRequest = new XMLDirectSignatureJobRequest("123abc", exitUrls, WAIT_FOR_CALLBACK, null); - MarshallingFailureException thrown = assertThrows(MarshallingFailureException.class, - () -> marshaller.marshal(signatureJobRequest, new StreamResult(new ByteArrayOutputStream()))); + RuntimeException thrown = assertThrows(RuntimeException.class, + () -> marshaller.marshal(signatureJobRequest, new StreamResult(new ByteArrayOutputStream()).getOutputStream())); assertThat(thrown, where(Exception::getMessage, allOf(containsString("completion-url"), containsString("is expected")))); } @@ -178,8 +177,8 @@ public void invalid_manifest_causes_exceptions() { XMLPortalSignatureJobManifest portalManifest = new XMLPortalSignatureJobManifest( asList(portalSigner), sender, null, "Title", "nonsensitive title", "Description", asList(portalDocument) , FOUR, new XMLAvailability(), PERSONAL_IDENTIFICATION_NUMBER_AND_NAME); - MarshallingFailureException marshallingFailure = - assertThrows(MarshallingFailureException.class, () -> marshaller.marshal(portalManifest, new StreamResult(new ByteArrayOutputStream()))); + RuntimeException marshallingFailure = + assertThrows(RuntimeException.class, () -> marshaller.marshal(portalManifest, new StreamResult(new ByteArrayOutputStream()).getOutputStream())); assertThat(marshallingFailure, where(Exception::getMessage, allOf(containsString("signature-type"), containsString("notifications-using-lookup"), containsString("notifications")))); } @@ -192,8 +191,8 @@ public void invalid_manifest_causes_exceptions() { void response_unmarshaller_ignores_unexpected_elements_in_response() throws Exception { XMLDirectSignatureJobStatusResponse unmarshalled; try (InputStream responseWithUnknownElement = getClass().getResourceAsStream("/xml/direct_signature_job_response_with_unexpected_element.xml")) { - unmarshalled = (XMLDirectSignatureJobStatusResponse) SignatureJaxb2Marshaller.ForResponsesOfAllApis.singleton() - .unmarshal(new StreamSource(responseWithUnknownElement)); + unmarshalled = JaxbMarshaller.ForResponsesOfAllApis.singleton().unmarshal( + new StreamSource(responseWithUnknownElement).getInputStream(), XMLDirectSignatureJobStatusResponse.class); } assertThat(unmarshalled, where(XMLDirectSignatureJobStatusResponse::getSignatureJobId, is(1L))); diff --git a/jaxb/src/test/java/no/digipost/signature/jaxb/spring/MarshallingMatchers.java b/jaxb/src/test/java/no/digipost/signature/jaxb/spring/MarshallingMatchers.java index 9c2cac14..77ea34c1 100644 --- a/jaxb/src/test/java/no/digipost/signature/jaxb/spring/MarshallingMatchers.java +++ b/jaxb/src/test/java/no/digipost/signature/jaxb/spring/MarshallingMatchers.java @@ -15,17 +15,17 @@ */ package no.digipost.signature.jaxb.spring; +import no.digipost.signature.jaxb.JaxbMarshaller; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeDiagnosingMatcher; import org.javers.core.Javers; import org.javers.core.diff.Diff; -import org.springframework.oxm.jaxb.Jaxb2Marshaller; -import org.springframework.xml.transform.StringSource; -import javax.xml.transform.stream.StreamResult; - -import java.io.CharArrayWriter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; import static no.digipost.DiggBase.friendlyName; import static no.digipost.DiggExceptions.exceptionNameAndMessage; @@ -33,10 +33,10 @@ final class MarshallingMatchers { - private final Jaxb2Marshaller marshaller; + private final JaxbMarshaller marshaller; private final Javers javers; - public MarshallingMatchers(Jaxb2Marshaller marshaller) { + public MarshallingMatchers(JaxbMarshaller marshaller) { this.marshaller = marshaller; this.javers = javers().build(); } @@ -52,9 +52,9 @@ public void describeTo(Description description) { @Override protected boolean matchesSafely(T item, Description mismatchDescription) { - try (CharArrayWriter xmlWriter = new CharArrayWriter()) { + try (ByteArrayOutputStream xmlWriter = new ByteArrayOutputStream()) { try { - marshaller.marshal(item, new StreamResult(xmlWriter)); + marshaller.marshal(item, xmlWriter); } catch (Exception e) { mismatchDescription .appendText("Unable to marshall ").appendValue(item).appendText(" to XML, because ") @@ -63,8 +63,8 @@ protected boolean matchesSafely(T item, Description mismatchDescription) { } String xml = xmlWriter.toString(); Object unmarshalled; - try { - unmarshalled = marshaller.unmarshal(new StringSource(xml)); + try(InputStream in = new ByteArrayInputStream(xml.getBytes())) { + unmarshalled = marshaller.unmarshal(in, item.getClass()); } catch (Exception e) { mismatchDescription .appendValue(item).appendText(" marshalled successfully to XML:\n").appendText(xml) @@ -83,6 +83,8 @@ protected boolean matchesSafely(T item, Description mismatchDescription) { .appendText(" differed from the expected object:\n").appendValue(diff); return false; } + } catch (IOException e) { + throw new RuntimeException(e); } } diff --git a/jaxb/src/test/resources/xml/direct_signature_job_response_with_unexpected_element.xml b/jaxb/src/test/resources/xml/direct_signature_job_response_with_unexpected_element.xml index 48ffa44a..9f075b9d 100644 --- a/jaxb/src/test/resources/xml/direct_signature_job_response_with_unexpected_element.xml +++ b/jaxb/src/test/resources/xml/direct_signature_job_response_with_unexpected_element.xml @@ -23,4 +23,4 @@ https://api.signering.posten.no/api/{sender-identifier}/direct/signature-jobs/1/complete https://api.signering.posten.no/api/{sender-identifier}/direct/signature-jobs/1/xades/1 https://api.signering.posten.no/api/{sender-identifier}/direct/signature-jobs/1/pades - \ No newline at end of file + From 0401ee0e25b7200a16c4d3b140fb0f683804a82a Mon Sep 17 00:00:00 2001 From: Rune Flobakk Date: Mon, 6 Feb 2023 16:09:28 +0100 Subject: [PATCH 2/9] Improve error message from Matcher Includes the whole cause message chain of the caught exception. --- .../signature/jaxb/spring/MarshallingMatchers.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/jaxb/src/test/java/no/digipost/signature/jaxb/spring/MarshallingMatchers.java b/jaxb/src/test/java/no/digipost/signature/jaxb/spring/MarshallingMatchers.java index 77ea34c1..5651a93d 100644 --- a/jaxb/src/test/java/no/digipost/signature/jaxb/spring/MarshallingMatchers.java +++ b/jaxb/src/test/java/no/digipost/signature/jaxb/spring/MarshallingMatchers.java @@ -15,6 +15,7 @@ */ package no.digipost.signature.jaxb.spring; +import no.digipost.DiggExceptions; import no.digipost.signature.jaxb.JaxbMarshaller; import org.hamcrest.Description; import org.hamcrest.Matcher; @@ -27,8 +28,9 @@ import java.io.IOException; import java.io.InputStream; +import static java.util.stream.Collectors.joining; import static no.digipost.DiggBase.friendlyName; -import static no.digipost.DiggExceptions.exceptionNameAndMessage; +import static no.digipost.DiggExceptions.causalChainOf; import static org.javers.core.JaversBuilder.javers; final class MarshallingMatchers { @@ -58,7 +60,9 @@ protected boolean matchesSafely(T item, Description mismatchDescription) { } catch (Exception e) { mismatchDescription .appendText("Unable to marshall ").appendValue(item).appendText(" to XML, because ") - .appendText(exceptionNameAndMessage(e)); + .appendText(causalChainOf(e) + .map(DiggExceptions::exceptionNameAndMessage) + .collect(joining(", caused by "))); return false; } String xml = xmlWriter.toString(); @@ -69,7 +73,10 @@ protected boolean matchesSafely(T item, Description mismatchDescription) { mismatchDescription .appendValue(item).appendText(" marshalled successfully to XML:\n").appendText(xml) .appendText("\nbut was unable to unmarshall back to ").appendText(friendlyName(item.getClass())) - .appendText(", because ").appendText(exceptionNameAndMessage(e)); + .appendText(", because ") + .appendText(causalChainOf(e) + .map(DiggExceptions::exceptionNameAndMessage) + .collect(joining(", caused by "))); return false; } From 16259b8f8fb1218b89d96d3397c071e6ddae451b Mon Sep 17 00:00:00 2001 From: Rune Flobakk Date: Mon, 6 Feb 2023 16:44:44 +0100 Subject: [PATCH 3/9] Catch all exceptions when trying to create Schema --- .../main/java/no/digipost/signature/jaxb/JaxbMarshaller.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java b/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java index 21bea8a1..eddbcd10 100644 --- a/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java +++ b/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java @@ -17,7 +17,6 @@ import no.digipost.signature.xsd.SignatureApiSchemas; import org.xml.sax.InputSource; -import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import javax.xml.XMLConstants; @@ -25,7 +24,6 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.Source; @@ -158,7 +156,7 @@ private static Schema createSchema(Collection resources) { SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = schemaFactory.newSchema(schemaSources); return schema; - } catch (SAXException | ParserConfigurationException e) { + } catch (Exception e) { throw new RuntimeException("Could not create schema from resources [" + String.join(", ", resources) + "]", e); } } From 5ccbb6cf2d0cc3d751f83867c20d853aec3e94f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simen=20St=C3=B8a?= Date: Tue, 7 Feb 2023 09:55:01 +0100 Subject: [PATCH 4/9] make ForRequestsOfAllApi public --- .../main/java/no/digipost/signature/jaxb/JaxbMarshaller.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java b/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java index eddbcd10..f0b4c645 100644 --- a/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java +++ b/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java @@ -57,7 +57,7 @@ public abstract class JaxbMarshaller { * This marshaller will validate if the XML generated from marshalled Java objects * adheres to the API schemas. */ - static class ForRequestsOfAllApis extends JaxbMarshaller { + public static class ForRequestsOfAllApis extends JaxbMarshaller { public static JaxbMarshaller singleton() { return SingletonHolder.instance; From 1dcef78280121b6c575b554650199a8a84795e75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simen=20St=C3=B8a?= Date: Wed, 8 Feb 2023 14:52:44 +0100 Subject: [PATCH 5/9] upgrade dependencies --- jaxb/pom.xml | 20 ++++++++++---------- pom.xml | 22 +++++++++++----------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/jaxb/pom.xml b/jaxb/pom.xml index b6385488..11bb70b6 100644 --- a/jaxb/pom.xml +++ b/jaxb/pom.xml @@ -22,7 +22,7 @@ org.junit junit-bom - 5.8.2 + 5.9.2 pom import @@ -38,7 +38,7 @@ org.glassfish.jaxb jaxb-runtime - 2.3.5 + 2.3.6 test @@ -84,31 +84,31 @@ nl.jqno.equalsverifier equalsverifier - 3.8 + 3.13 test org.javers javers-core - 6.5.3 + 6.9.1 test no.digipost digg - 0.30 + 0.33 test org.slf4j jcl-over-slf4j - 1.7.32 + 2.0.5 test org.slf4j slf4j-simple - 1.7.32 + 2.0.5 test @@ -123,7 +123,7 @@ maven-javadoc-plugin - 3.3.1 + 3.4.1 no.digipost.signature.api.xml.* false @@ -140,7 +140,7 @@ com.github.siom79.japicmp japicmp-maven-plugin - 0.15.4 + 0.17.1 @@ -205,7 +205,7 @@ org.glassfish.jaxb jaxb-runtime - 2.3.5 + 2.3.6 diff --git a/pom.xml b/pom.xml index f6344d57..53af71be 100644 --- a/pom.xml +++ b/pom.xml @@ -33,27 +33,27 @@ maven-dependency-plugin - 3.1.2 + 3.3.0 maven-help-plugin - 3.2.0 + 3.3.0 maven-clean-plugin - 3.1.0 + 3.2.0 maven-resources-plugin - 3.2.0 + 3.3.0 maven-compiler-plugin - 3.8.1 + 3.10.1 maven-enforcer-plugin - 3.0.0 + 3.2.1 @@ -73,7 +73,7 @@ maven-surefire-plugin - 3.0.0-M5 + 3.0.0-M7 org.jasig.maven @@ -90,7 +90,7 @@ org.glassfish.jaxb jaxb-runtime - 2.3.5 + 2.3.6 jakarta.xml.bind @@ -132,15 +132,15 @@ maven-jar-plugin - 3.2.0 + 3.3.0 maven-install-plugin - 3.0.0-M1 + 3.0.1 maven-deploy-plugin - 3.0.0-M1 + 3.0.0 org.codehaus.mojo From 3e413a66a007edafedaedbb879399adac2f2fa1c Mon Sep 17 00:00:00 2001 From: Rune Flobakk Date: Tue, 14 Feb 2023 09:38:47 +0100 Subject: [PATCH 6/9] Upgrade Maven plugins --- pom.xml | 54 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/pom.xml b/pom.xml index 53af71be..52fedf9f 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ maven-dependency-plugin - 3.3.0 + 3.5.0 maven-help-plugin @@ -57,9 +57,7 @@ - - 3.3.1 + 3.6.3 @@ -73,7 +71,7 @@ maven-surefire-plugin - 3.0.0-M7 + 3.0.0-M9 org.jasig.maven @@ -104,30 +102,34 @@ license-maven-plugin 4.1 -

src/license-header.txt
true true true XML_STYLE - - **/pom.xml - src/validation/*.* - xsd/thirdparty/*.* - xsd/catalog.xml - examples/**/* - NOTICE - **/LICENSE - src/notice/NOTICE.template - src/notice/license-mappings.xml - jaxb/*.xjb - integrasjon/** - docs/** - .github/**/*.yml - .java-version - .mvn/maven.config - + + +
src/license-header.txt
+ + **/pom.xml + src/validation/*.* + xsd/thirdparty/*.* + xsd/catalog.xml + examples/**/* + NOTICE + **/LICENSE + src/notice/NOTICE.template + src/notice/license-mappings.xml + jaxb/*.xjb + integrasjon/** + docs/** + .github/**/*.yml + .java-version + .mvn/maven.config + +
+
@@ -136,16 +138,16 @@ maven-install-plugin - 3.0.1 + 3.1.0 maven-deploy-plugin - 3.0.0 + 3.1.0 org.codehaus.mojo versions-maven-plugin - 2.8.1 + 2.14.2 From 9c42c4630e2e212fac959adf095d28b01f8055b4 Mon Sep 17 00:00:00 2001 From: Rune Flobakk Date: Tue, 14 Feb 2023 09:48:41 +0100 Subject: [PATCH 7/9] Upgrade dependencies --- jaxb/pom.xml | 4 ++-- jaxb/src/test/resources/simplelogger.properties | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 jaxb/src/test/resources/simplelogger.properties diff --git a/jaxb/pom.xml b/jaxb/pom.xml index 11bb70b6..fea4af39 100644 --- a/jaxb/pom.xml +++ b/jaxb/pom.xml @@ -84,7 +84,7 @@ nl.jqno.equalsverifier equalsverifier - 3.13 + 3.13.1 test @@ -101,7 +101,7 @@ org.slf4j - jcl-over-slf4j + slf4j-api 2.0.5 test diff --git a/jaxb/src/test/resources/simplelogger.properties b/jaxb/src/test/resources/simplelogger.properties new file mode 100644 index 00000000..8b202875 --- /dev/null +++ b/jaxb/src/test/resources/simplelogger.properties @@ -0,0 +1,17 @@ +# +# Copyright (C) Posten Norge AS +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +org.slf4j.simpleLogger.defaultLogLevel=warn \ No newline at end of file From 9550d1daea9c30ea3e1980d7e12062fdb4eb54a9 Mon Sep 17 00:00:00 2001 From: Rune Flobakk Date: Tue, 14 Feb 2023 10:46:43 +0100 Subject: [PATCH 8/9] Upgrade Git workflow actions --- .github/workflows/build.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d28f0adb..30990dd6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,17 +7,18 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ '1.8', '11' ] + java: [ '8', '11' ] name: build java ${{ matrix.java }} steps: - - uses: actions/checkout@v1 - - name: Set up java - uses: actions/setup-java@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3.6.0 with: + distribution: temurin java-version: ${{ matrix.java }} + cache: "maven" - name: Build with Maven - run: mvn -B package --no-transfer-progress --file pom.xml + run: mvn -B clean verify --no-transfer-progress --show-version makeversion: if: github.ref != 'refs/heads/main' @@ -44,7 +45,7 @@ jobs: name: Deploy snapshot steps: - uses: actions/checkout@v1 - - uses: digipost/action-maven-publish@1.1.0 + - uses: digipost/action-maven-publish@1.3.0 with: sonatype_secrets: ${{ secrets.sonatype_secrets }} release_version: ${{ needs.makeversion.outputs.version }} @@ -59,7 +60,7 @@ jobs: - name: Check out Git repository uses: actions/checkout@v1 - name: Release to Central Repository - uses: digipost/action-maven-publish@1.1.0 + uses: digipost/action-maven-publish@1.3.0 with: sonatype_secrets: ${{ secrets.sonatype_secrets }} release_version: ${{ needs.makeversion.outputs.version }} From d6723869b4591620973c8a807121bde7d06ffe2b Mon Sep 17 00:00:00 2001 From: Rune Flobakk Date: Tue, 14 Feb 2023 16:20:41 +0100 Subject: [PATCH 9/9] Provide unmarshalling from byte-array --- .../no/digipost/signature/jaxb/JaxbMarshaller.java | 12 ++++++++---- .../signature/jaxb/spring/JaxbMarshallerTest.java | 9 ++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java b/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java index f0b4c645..95f20107 100644 --- a/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java +++ b/jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java @@ -50,7 +50,7 @@ * @see JaxbMarshaller.ForResponsesOfAllApis * @see JaxbMarshaller.ForRequestsOfAllApis */ -public abstract class JaxbMarshaller { +public class JaxbMarshaller { /** * Marshaller for creating requests for both the Direct and Portal API. @@ -173,13 +173,13 @@ private static JAXBContext initContext(Collection> classes) { private final JAXBContext jaxbContext; private final Optional schema; - JaxbMarshaller(Set> classes, Set schemaResources) { + public JaxbMarshaller(Set> classes, Set schemaResources) { this.jaxbContext = initContext(classes); this.schema = Optional.ofNullable(schemaResources).filter(s -> !s.isEmpty()).map(JaxbMarshaller::createSchema); } - JaxbMarshaller(Set> classes) { - this(classes, null); + public JaxbMarshaller(Set> classes) { + this(classes, null); } public void marshal(Object object, OutputStream outputStream){ @@ -202,4 +202,8 @@ public T unmarshal(InputStream inputStream, Class type){ } } + public T unmarshal(byte[] bytes, Class type) { + return unmarshal(new ByteArrayInputStream(bytes), type); + } + } diff --git a/jaxb/src/test/java/no/digipost/signature/jaxb/spring/JaxbMarshallerTest.java b/jaxb/src/test/java/no/digipost/signature/jaxb/spring/JaxbMarshallerTest.java index 20d8650b..e7768322 100644 --- a/jaxb/src/test/java/no/digipost/signature/jaxb/spring/JaxbMarshallerTest.java +++ b/jaxb/src/test/java/no/digipost/signature/jaxb/spring/JaxbMarshallerTest.java @@ -37,7 +37,6 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import java.io.ByteArrayOutputStream; @@ -46,7 +45,6 @@ import java.time.ZoneId; import java.time.ZonedDateTime; -import static uk.co.probablyfine.matchers.Java8Matchers.where; import static java.time.temporal.ChronoUnit.MILLIS; import static java.util.Arrays.asList; import static no.digipost.signature.api.xml.XMLAuthenticationLevel.FOUR; @@ -61,6 +59,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.sameInstance; import static org.junit.jupiter.api.Assertions.assertThrows; +import static uk.co.probablyfine.matchers.Java8Matchers.where; class JaxbMarshallerTest { @@ -113,7 +112,7 @@ void invalid_manifest_causes_exceptions() { RuntimeException marshallingFailure = - assertThrows(RuntimeException.class, () -> marshaller.marshal(directManifest, new StreamResult(new ByteArrayOutputStream()).getOutputStream())); + assertThrows(RuntimeException.class, () -> marshaller.marshal(directManifest, new ByteArrayOutputStream())); assertThat(marshallingFailure, where(Exception::getMessage, allOf(containsString("href"), containsString("must appear")))); } @@ -128,7 +127,7 @@ void invalid_signature_job_request_causes_exceptions() { XMLDirectSignatureJobRequest signatureJobRequest = new XMLDirectSignatureJobRequest("123abc", exitUrls, WAIT_FOR_CALLBACK, null); RuntimeException thrown = assertThrows(RuntimeException.class, - () -> marshaller.marshal(signatureJobRequest, new StreamResult(new ByteArrayOutputStream()).getOutputStream())); + () -> marshaller.marshal(signatureJobRequest, new ByteArrayOutputStream())); assertThat(thrown, where(Exception::getMessage, allOf(containsString("completion-url"), containsString("is expected")))); } @@ -178,7 +177,7 @@ public void invalid_manifest_causes_exceptions() { asList(portalSigner), sender, null, "Title", "nonsensitive title", "Description", asList(portalDocument) , FOUR, new XMLAvailability(), PERSONAL_IDENTIFICATION_NUMBER_AND_NAME); RuntimeException marshallingFailure = - assertThrows(RuntimeException.class, () -> marshaller.marshal(portalManifest, new StreamResult(new ByteArrayOutputStream()).getOutputStream())); + assertThrows(RuntimeException.class, () -> marshaller.marshal(portalManifest, new ByteArrayOutputStream())); assertThat(marshallingFailure, where(Exception::getMessage, allOf(containsString("signature-type"), containsString("notifications-using-lookup"), containsString("notifications")))); }