Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright (C) 2018-2019 toop.eu
*
* 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 eu.toop.connector.me;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Locale;
import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.xml.XMLConstants;
import javax.xml.bind.DatatypeConverter;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import com.helger.commons.ValueEnforcer;
import com.helger.commons.charset.CharsetHelper;
import com.helger.commons.error.level.EErrorLevel;
import com.helger.commons.io.ByteArrayWrapper;
import com.helger.commons.io.resource.ClassPathResource;
import com.helger.commons.io.stream.NonBlockingByteArrayOutputStream;
import com.helger.commons.mime.CMimeType;
import com.helger.commons.mime.MimeType;
import com.helger.commons.mime.MimeTypeParser;
import com.helger.commons.mime.MimeTypeParserException;
import com.helger.commons.regex.RegExHelper;
import com.helger.commons.string.StringHelper;
import com.helger.xml.microdom.IMicroDocument;
import com.helger.xml.microdom.IMicroElement;
import com.helger.xml.microdom.MicroDocument;
import com.helger.xml.microdom.MicroElement;
import com.helger.xml.microdom.serialize.MicroWriter;
import com.helger.xml.namespace.MapBasedNamespaceContext;
import com.helger.xml.serialize.read.DOMReader;
import com.helger.xml.serialize.write.XMLWriterSettings;
import com.helger.xml.transform.TransformSourceFactory;
import eu.toop.commons.error.EToopErrorCode;
import eu.toop.connector.api.TCConfig;
import eu.toop.connector.api.as4.MEException;
import eu.toop.connector.api.as4.MEMessage;
import eu.toop.connector.api.as4.MEPayload;
import eu.toop.connector.me.notifications.RelayResult;
import eu.toop.connector.me.notifications.SubmissionResult;
import eu.toop.kafkaclient.ToopKafkaClient;
public final class EBMSUtils {
private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(EBMSUtils.class);
// SOAP 1.2 NS
public static final String NS_SOAPENV = "http://www.w3.org/2003/05/soap-envelope";
public static final String NS_EBMS = "http://docs.oasis-open.org/ebxml-msg/ebms/v3.0/ns/core/200704/";
private EBMSUtils() {
}
/*
* See
* http://docs.oasis-open.org/ebxml-msg/ebms/v3.0/profiles/AS4-profile/v1.0/os/
* AS4-profile-v1.0-os.html#__RefHeading__26454_1909778835
*/
public static byte[] createSuccessReceipt(final SOAPMessage message) {
ValueEnforcer.notNull(message, "SOAPMessage");
try {
final StreamSource stylesource = TransformSourceFactory.create(new ClassPathResource("/receipt-generator.xslt"));
final TransformerFactory transformerFactory = TransformerFactory.newInstance ();
transformerFactory.setFeature (XMLConstants.FEATURE_SECURE_PROCESSING, true);
final Transformer transformer = transformerFactory.newTransformer(stylesource);
transformer.setParameter("messageid", genereateEbmsMessageId(MEMConstants.MEM_AS4_SUFFIX));
transformer.setParameter("timestamp", DateTimeUtils.getCurrentTimestamp());
try (final NonBlockingByteArrayOutputStream baos = new NonBlockingByteArrayOutputStream()) {
transformer.transform(new DOMSource(message.getSOAPPart()), new StreamResult(baos));
return baos.toByteArray();
}
} catch (final RuntimeException ex) {
// throw RTE's directly
throw ex;
} catch (final Exception ex) {
// force exceptions to runtime
throw new MEException(ex.getMessage(), ex);
}
}
/**
* Create a fault message based on the error message
*
* @param soapMessage Source SOAP message. May be null
* @param faultMessage Fault message. May be null.
* @return byte[] with result XML SOAP Fault message
*/
public static byte[] createFault(@Nullable final SOAPMessage soapMessage, @Nullable final String faultMessage) {
final String fm = faultMessage != null ? faultMessage : "Unknown Error";
String refToMessageInError;
if (soapMessage != null) {
refToMessageInError = getMessageId(soapMessage);
} else {
refToMessageInError = "";
}
final IMicroDocument aDoc = new MicroDocument();
final IMicroElement eEnvelope = aDoc.appendElement(NS_SOAPENV, "Envelope");
{
final IMicroElement eHeader = eEnvelope.appendElement(NS_SOAPENV, "Head");
final IMicroElement eMessaging = eHeader.appendElement(NS_EBMS, "Messaging");
final IMicroElement eSignalMessage = eMessaging.appendElement(NS_EBMS, "SignalMessage");
{
final IMicroElement eMessageInfo = eSignalMessage.appendElement(NS_EBMS, "MessageInfo");
eMessageInfo.appendElement(NS_EBMS, "Timestamp").appendText(DateTimeUtils.getCurrentTimestamp());
final String ebmsMessageId = genereateEbmsMessageId(MEMConstants.MEM_AS4_SUFFIX);
eMessageInfo.appendElement(NS_EBMS, "MessageId").appendText(ebmsMessageId);
}
{
final IMicroElement eError = eSignalMessage.appendElement(NS_EBMS, "Error");
eError.setAttribute("category", "CONTENT");
eError.setAttribute("errorCode", "EBMS:0004");
eError.setAttribute("origin", "ebms");
eError.setAttribute("refToMessageInError", refToMessageInError);
eError.setAttribute("severity", "failure");
eError.setAttribute("shortDescription", "Error");
eError.appendElement(NS_EBMS, "Description").setAttribute(XMLConstants.XML_NS_URI, "lang", "en")
.appendText(fm);
eError.appendElement(NS_EBMS, "ErrorDetail").appendText(fm);
}
}
{
final IMicroElement eBody = eEnvelope.appendElement(NS_SOAPENV, "Body");
final IMicroElement eFault = eBody.appendElement(NS_SOAPENV, "Fault");
{
final IMicroElement eCode = eFault.appendElement(NS_SOAPENV, "Code");
eCode.appendElement(NS_SOAPENV, "Value").appendText("env:Receiver");
}
{
final IMicroElement eReason = eFault.appendElement(NS_SOAPENV, "Reason");
eReason.appendElement(NS_SOAPENV, "Text").setAttribute(XMLConstants.XML_NS_URI, "lang", "en").appendText(fm);
}
}
final MapBasedNamespaceContext aNSCtx = new MapBasedNamespaceContext();
aNSCtx.addMapping("env", NS_SOAPENV);
aNSCtx.addMapping("eb", NS_EBMS);
return MicroWriter.getNodeAsBytes(aDoc, new XMLWriterSettings().setNamespaceContext(aNSCtx));
}
/**
* Generate a random ebms message id with the format <RANDOM UUID>@ext
*
* @param ext suffix to use. May not be null.
* @return EBMS Message ID. Never null nor empty.
*/
public static String genereateEbmsMessageId(final String ext) {
return UUID.randomUUID().toString() + "@" + ext;
}
@Nullable
private static IMicroElement _property(@Nonnull final String sName, @Nullable final String sValue) {
if (sValue == null) {
return null;
}
final IMicroElement ret = new MicroElement(NS_EBMS, "Property");
ret.setAttribute("name", sName).appendText(sValue);
return ret;
}
/*
* The conversion procedure goes here
*/
public static SOAPMessage convert2MEOutboundAS4Message(final SubmissionMessageProperties metadata,
final MEMessage meMessage) {
if (LOG.isDebugEnabled()) {
LOG.debug("Convert submission data to SOAP Message");
}
try {
final IMicroDocument aDoc = new MicroDocument();
final IMicroElement eMessaging = aDoc.appendElement(NS_EBMS, "Messaging");
eMessaging.setAttribute(NS_SOAPENV, "mustUnderstand", "true");
final IMicroElement eUserMessage = eMessaging.appendElement(NS_EBMS, "UserMessage");
{
final IMicroElement eMessageInfo = eUserMessage.appendElement(NS_EBMS, "MessageInfo");
eMessageInfo.appendElement(NS_EBMS, "Timestamp").appendText(DateTimeUtils.getCurrentTimestamp());
final String ebmsMessageId = genereateEbmsMessageId(MEMConstants.MEM_AS4_SUFFIX);
eMessageInfo.appendElement(NS_EBMS, "MessageId").appendText(ebmsMessageId);
}
{
final IMicroElement ePartyInfo = eUserMessage.appendElement(NS_EBMS, "PartyInfo");
{
final IMicroElement eFrom = ePartyInfo.appendElement(NS_EBMS, "From");
eFrom.appendElement(NS_EBMS, "PartyId")
// .setAttribute ("type", "urn:oasis:names:tc:ebcore:partyid-type:unregistered")
.appendText(TCConfig.getMEMAS4TcPartyid());
eFrom.appendElement(NS_EBMS, "Role").appendText(MEMConstants.MEM_PARTY_ROLE);
}
{
final IMicroElement eTo = ePartyInfo.appendElement(NS_EBMS, "To");
eTo.appendElement(NS_EBMS, "PartyId").appendText(TCConfig.getMEMAS4GwPartyID());
eTo.appendElement(NS_EBMS, "Role").appendText(MEMConstants.GW_PARTY_ROLE);
}
}
{
final IMicroElement eCollaborationInfo = eUserMessage.appendElement(NS_EBMS, "CollaborationInfo");
eCollaborationInfo.appendElement(NS_EBMS, "Service").appendText(MEMConstants.SERVICE);
eCollaborationInfo.appendElement(NS_EBMS, "Action").appendText(MEMConstants.ACTION_SUBMIT);
eCollaborationInfo.appendElement(NS_EBMS, "ConversationId").appendText(metadata.conversationId);
}
{
final IMicroElement eMessageProperties = eUserMessage.appendElement(NS_EBMS, "MessageProperties");
eMessageProperties.appendChild(_property("MessageId", metadata.messageId));
eMessageProperties.appendChild(_property("ConversationId", metadata.conversationId));
eMessageProperties.appendChild(_property("RefToMessageId", metadata.refToMessageId));
eMessageProperties.appendChild(_property("Service", metadata.service));
eMessageProperties.appendChild(_property("Action", metadata.action));
eMessageProperties.appendChild(_property("ToPartyId", metadata.toPartyId));
eMessageProperties.appendChild(_property("ToPartyIdType", metadata.toPartyIdType));
eMessageProperties.appendChild(_property("ToPartyRole", metadata.toPartyRole));
// NOTE: ToPartyCertificate is the DER+BASE64 encoded X509 certificate.
// First decode as byte array, then parse it using
// CertificateFactory.getInstance("X509", "BC")
// recommended provider: BouncyCastleProvider
eMessageProperties.appendChild(_property("ToPartyCertificate", metadata.toPartyCertificate));
eMessageProperties.appendChild(_property("TargetURL", metadata.targetURL));
}
{
final IMicroElement ePayloadInfo = eUserMessage.appendElement(NS_EBMS, "PayloadInfo");
for (final MEPayload aPayload : meMessage.payloads()) {
final IMicroElement ePartInfo = ePayloadInfo.appendElement(NS_EBMS, "PartInfo");
ePartInfo.setAttribute("href", "cid:" + aPayload.getPayloadId());
final IMicroElement ePartProperties = ePartInfo.appendElement(NS_EBMS, "PartProperties");
ePartProperties.appendChild(_property("MimeType", aPayload.getMimeTypeString()));
}
}
final MapBasedNamespaceContext aNSCtx = new MapBasedNamespaceContext();
aNSCtx.addMapping("env", NS_SOAPENV);
aNSCtx.addMapping("eb", NS_EBMS);
// Convert to org.w3c.dom ....
final Element element = DOMReader.readXMLDOM(MicroWriter.getNodeAsBytes(aDoc,
new XMLWriterSettings().setNamespaceContext(aNSCtx)))
.getDocumentElement();
// create a soap message based on this XML
final SOAPMessage message = SoapUtil.createEmptyMessage();
final Node importNode = message.getSOAPHeader().getOwnerDocument().importNode(element, true);
message.getSOAPHeader().appendChild(importNode);
meMessage.payloads().forEach(payload -> {
final AttachmentPart attachmentPart = message.createAttachmentPart();
attachmentPart.setContentId('<' + payload.getPayloadId() + '>');
try {
attachmentPart.setRawContentBytes(payload.getData ().bytes (),
payload.getData ().getOffset (),
payload.getData ().size (),
payload.getMimeTypeString());
} catch (final SOAPException e) {
throw new MEException(e);
}
message.addAttachmentPart(attachmentPart);
});
if (message.saveRequired()) {
message.saveChanges();
}
if (LOG.isTraceEnabled()) {
LOG.trace(SoapUtil.describe(message));
}
return message;
} catch (final Exception ex) {
throw new MEException(ex);
}
}
/**
* Process the inbound SOAPMessage and convert it to the MEMEssage
*
* @param message the soap message to be converted to a MEMessage. Cannot be null
* @return the MEMessage object created from the supplied SOAPMessage
* @throws MEException in case of error
*/
public static MEMessage soap2MEMessage(@Nonnull final SOAPMessage message) {
ValueEnforcer.notNull(message, "SOAPMessage");
if (LOG.isDebugEnabled()) {
LOG.debug("Convert message to submission data");
}
final MEMessage meMessage = new MEMessage();
if (message.countAttachments() > 0) {
// Read all attachments
message.getAttachments().forEachRemaining(attObj -> {
final AttachmentPart att = (AttachmentPart) attObj;
// remove surplus characters
final String href = RegExHelper.stringReplacePattern("<|>", att.getContentId(), "");
Node partInfo;
try {
// throws exception if part info does not exist
partInfo = SoapXPathUtil.safeFindSingleNode(message.getSOAPHeader(),
"//:PayloadInfo/:PartInfo[@href='cid:" + href + "']");
} catch (final Exception ex) {
throw new MEException("ContentId: " + href + " was not found in PartInfo");
}
MimeType mimeType;
try {
String sMimeType = SoapXPathUtil.getSingleNodeTextContent(partInfo,
".//:PartProperties/:Property[@name='MimeType']");
if (sMimeType.startsWith("cid:")) {
sMimeType = sMimeType.substring(4);
}
mimeType = MimeTypeParser.parseMimeType(sMimeType);
} catch (final MimeTypeParserException ex) {
LOG.warn("Error parsing MIME type: " + ex.getMessage());
// if there is a problem wrt the processing of the mimetype, simply grab the
// content type
// FIXME: Do not swallow the error, there might a problem with the mimtype
mimeType = MimeTypeParser.parseMimeType(att.getContentType());
}
try {
final Node charSetNode = SoapXPathUtil.findSingleNode(partInfo,
".//:PartProperties/:Property[@name='CharacterSet']/text()");
if (charSetNode != null) {
final Charset aCharset = CharsetHelper.getCharsetFromNameOrNull(charSetNode.getNodeValue());
if (aCharset != null) {
// Add charset to MIME type
mimeType.addParameter(CMimeType.PARAMETER_NAME_CHARSET, aCharset.name());
}
}
} catch (final MEException ex) {
// ignore
}
byte[] rawContentBytes;
try {
rawContentBytes = att.getRawContentBytes();
} catch (final SOAPException e) {
throw new MEException(e);
}
final MEPayload payload = new MEPayload(mimeType, href, new ByteArrayWrapper (rawContentBytes, false));
if (LOG.isDebugEnabled()) {
LOG.debug("\tpayload.payloadId: " + payload.getPayloadId());
LOG.debug("\tpayload.mimeType: " + payload.getMimeTypeString());
}
meMessage.payloads().add(payload);
});
}
return meMessage;
}
public static RelayResult soap2RelayResult(final SOAPMessage sNotification) {
ValueEnforcer.notNull(sNotification, "Notification");
final RelayResult notification = new RelayResult();
try {
final Node messagePropsNode = SoapXPathUtil.safeFindSingleNode(sNotification.getSOAPHeader(),
"//:MessageProperties");
final String messageId = SoapXPathUtil.getSingleNodeTextContent(messagePropsNode,
".//:Property[@name='MessageId']/text()");
notification.setMessageID(messageId);
final String refToMessageId = SoapXPathUtil.getSingleNodeTextContent(messagePropsNode,
".//:Property[@name='RefToMessageId']/text()");
notification.setRefToMessageID(refToMessageId);
final String sSignalType = SoapXPathUtil.getSingleNodeTextContent(messagePropsNode, ".//:Property[@name='Result']");
if (!"ERROR".equalsIgnoreCase(sSignalType)) {
notification.setResult(ResultType.RECEIPT);
} else {
notification.setResult(ResultType.ERROR);
try {
final String errorCode = SoapXPathUtil.getSingleNodeTextContent(messagePropsNode,
".//:Property[@name='ErrorCode']");
notification.setErrorCode(errorCode);
} catch (final MEException e) {
throw new IllegalStateException("ErrorCode is mandatory for relay result errors.");
}
try {
final String severity = SoapXPathUtil.getSingleNodeTextContent(messagePropsNode, ".//:Property[@name='severity']");
notification.setSeverity(severity);
} catch (final MEException e) {
// TODO so what?
}
try {
final String shortDesc = SoapXPathUtil.getSingleNodeTextContent(messagePropsNode,
".//:Property[@name='ShortDescription']");
notification.setShortDescription(shortDesc);
} catch (final MEException ignored) {
// TODO so what?
}
try {
final String desc = SoapXPathUtil.getSingleNodeTextContent(messagePropsNode, ".//:Property[@name='Description']");
notification.setDescription(desc);
} catch (final MEException ignored) {
// TODO so what?
}
}
return notification;
} catch (final RuntimeException ex) {
throw ex;
} catch (final SOAPException ex) {
throw new MEException(ex);
}
}
public static SubmissionResult soap2SubmissionResult(final SOAPMessage sSubmissionResult) {
ValueEnforcer.notNull(sSubmissionResult, "SubmissionResult");
final SubmissionResult submissionResult = new SubmissionResult();
try {
final Node messagePropsNode = SoapXPathUtil
.safeFindSingleNode(sSubmissionResult.getSOAPHeader(), "//:MessageProperties");
final String refToMessageID = SoapXPathUtil
.getSingleNodeTextContent(messagePropsNode, ".//:Property[@name='RefToMessageId']/text()");
submissionResult.setRefToMessageID(refToMessageID);
final String sSignalType = SoapXPathUtil.getSingleNodeTextContent(messagePropsNode, ".//:Property[@name='Result']");
if ("ERROR".equalsIgnoreCase(sSignalType)) {
submissionResult.setResult(ResultType.ERROR);
//description must be there when there is an error
final String description = SoapXPathUtil.getSingleNodeTextContent(messagePropsNode, ".//:Property[@name='Description']");
submissionResult.setDescription(description);
} else {
submissionResult.setResult(ResultType.RECEIPT);
//message id is conditional, it must be there only in case of receipt
final String messageID = SoapXPathUtil
.getSingleNodeTextContent(messagePropsNode, ".//:Property[@name='MessageId']/text()");
submissionResult.setMessageID(messageID);
}
return submissionResult;
} catch (final RuntimeException ex) {
throw ex;
} catch (final Exception ex) {
throw new MEException(ex);
}
}
@Nonnull
private static String _getCN(@Nonnull final String sPrincipal) {
try {
for (final Rdn aRdn : new LdapName(sPrincipal).getRdns()) {
if (aRdn.getType().equalsIgnoreCase("CN")) {
return (String) aRdn.getValue();
}
}
throw new IllegalStateException("Failed to get CN from '" + sPrincipal + "'");
} catch (final InvalidNameException ex) {
throw new IllegalStateException("Failed to get CN from '" + sPrincipal + "'", ex);
}
}
/**
* process the GatewayRoutingMetadata object and obtain the actual submission data. Use for any direction (DC -> DP
* and DP -> DC)
*
* @return SubmissionData
*/
static SubmissionMessageProperties inferSubmissionData(final GatewayRoutingMetadata gatewayRoutingMetadata) {
final X509Certificate certificate = gatewayRoutingMetadata.getCertificate();
// we need the certificate to obtain the to party id
ValueEnforcer.notNull(certificate, "Endpoint Certificate");
final SubmissionMessageProperties submissionData = new SubmissionMessageProperties();
submissionData.messageId = genereateEbmsMessageId(MEMConstants.MEM_AS4_SUFFIX);
submissionData.action = gatewayRoutingMetadata.getDocumentTypeId();
submissionData.service = gatewayRoutingMetadata.getProcessId();
submissionData.toPartyId = _getCN(gatewayRoutingMetadata.getCertificate()
.getSubjectX500Principal().getName());
// TODO: infer it from the transaction id
submissionData.conversationId = "1";
//this is the role of the RECEIVING gateway, it has been set
//to the role of the SENDING gateway (i.e MEMConstants.GW_PARTY_ROLE)
submissionData.toPartyRole = MEMConstants.GW_PARTY_ROLE;
submissionData.targetURL = gatewayRoutingMetadata.getEndpointUrl ();
try {
// DER encoded X509 certificate
final byte[] certBytes = gatewayRoutingMetadata.getCertificate().getEncoded();
// base 64 encoded DER bytes (i.e. converted to CER)
submissionData.toPartyCertificate = DatatypeConverter.printBase64Binary(certBytes);
} catch (final CertificateEncodingException e) {
throw new MEException(e);
}
return submissionData;
}
/**
* Calls {@link SoapUtil#sendSOAPMessage(SOAPMessage, URL)} but checks the return value for a fault or a receipt.
*
* @param soapMessage Message to be sent. May not be null
* @param url Target URL. May not be null
* @throws MEException if a fault is received instead of an ebms receipt
*/
public static void sendSOAPMessage(@Nonnull final SOAPMessage soapMessage, @Nonnull final URL url) {
ValueEnforcer.notNull(soapMessage, "SOAP Message");
ValueEnforcer.notNull(url, "Target url");
if (LOG.isTraceEnabled()) {
LOG.trace(SoapUtil.describe(soapMessage));
}
final SOAPMessage response = SoapUtil.sendSOAPMessage(soapMessage, url);
if (response != null) {
if (LOG.isTraceEnabled()) {
LOG.info(SoapUtil.describe(response));
}
validateReceipt(response);
} // else the receipt is null and we received a HTTP.OK, isn't that great?
}
/**
* Check if the response is a soap fault (i.e. the response contains an error)
*/
private static void validateReceipt(@Nonnull final SOAPMessage response) {
ValueEnforcer.notNull(response, "Soap message");
final Element errorElement = (Element) SoapXPathUtil.findSingleNode(response.getSOAPPart(),
"//:SignalMessage/:Error");
if (errorElement != null) {
final String cat = StringHelper.getNotNull(errorElement.getAttribute("category")).toUpperCase(Locale.US);
final String shortDescription = StringHelper.getNotNull(errorElement.getAttribute("shortDescription"))
.toUpperCase(Locale.US);
final String severity = StringHelper.getNotNull(errorElement.getAttribute("severity")).toUpperCase(Locale.US);
final String code = StringHelper.getNotNull(errorElement.getAttribute("errorCode")).toUpperCase(Locale.US);
final StringBuilder errBuff = new StringBuilder();
errBuff.append("EBMS ERROR CODE: [" + code + "]\n");
errBuff.append("Severity: [" + severity + "]\n");
errBuff.append("Category: [" + cat + "]\n");
errBuff.append("ShortDescription: [" + shortDescription
+ "]\n");
ToopKafkaClient.send(EErrorLevel.ERROR, () -> "Error from AS4 transmission: EToopErrorCode.ME_002 -- " + errBuff.toString());
throw new MEException(EToopErrorCode.ME_002, errBuff.toString());
}
// Short info that it worked
ToopKafkaClient.send(EErrorLevel.INFO, () -> "AS4 transmission seemed to have worked out fine");
}
/**
* Find the //:MessageInfo/eb:MessageId.text and return it.
*
* @param soapMessage SOAP message to extract data from
* @return The message ID
* @throws MEException if the message header does not contain an ebms message id
*/
public static String getMessageId(final SOAPMessage soapMessage) {
try {
return SoapXPathUtil.getSingleNodeTextContent(soapMessage.getSOAPHeader(),
"//:MessageInfo/:MessageId");
} catch (final SOAPException e) {
throw new MEException(e);
}
}
}