use of com.helger.phase4.dump.IAS4OutgoingDumper in project phase4 by phax.
the class AbstractAS4Client method sendMessageWithRetries.
/**
* Send the AS4 client message created by
* {@link #buildMessage(String, IAS4ClientBuildMessageCallback)} to the
* provided URL. This methods does take retries into account. It synchronously
* handles the retries and only returns after the last retry.
*
* @param <T>
* The response data type
* @param sURL
* The URL to send the HTTP POST to
* @param aResponseHandler
* The response handler that converts the HTTP response to a domain
* object. May not be <code>null</code>.
* @param aCallback
* An optional callback for the different stages of building the
* document. May be <code>null</code>.
* @param aOutgoingDumper
* An outgoing dumper to be used. Maybe <code>null</code>. If
* <code>null</code> the global outgoing dumper from
* {@link AS4DumpManager} is used.
* @param aRetryCallback
* An optional callback to be invoked if a retry happens on HTTP level.
* May be <code>null</code>.
* @return The sent message that contains
* @throws IOException
* in case of error when building or sending the message
* @throws WSSecurityException
* In case there is an issue with signing/encryption
* @throws MessagingException
* in case something happens in MIME wrapping
* @since 0.9.14
*/
@Nonnull
public final <T> AS4ClientSentMessage<T> sendMessageWithRetries(@Nonnull final String sURL, @Nonnull final ResponseHandler<? extends T> aResponseHandler, @Nullable final IAS4ClientBuildMessageCallback aCallback, @Nullable final IAS4OutgoingDumper aOutgoingDumper, @Nullable final IAS4RetryCallback aRetryCallback) throws IOException, WSSecurityException, MessagingException {
// Create a new message ID for each build!
final String sMessageID = createMessageID();
final AS4ClientBuiltMessage aBuiltMsg = buildMessage(sMessageID, aCallback);
HttpEntity aBuiltEntity = aBuiltMsg.getHttpEntity();
final HttpHeaderMap aBuiltHttpHeaders = aBuiltMsg.getCustomHeaders();
if (m_aHttpRetrySettings.isRetryEnabled() || aOutgoingDumper != null || AS4DumpManager.getOutgoingDumper() != null) {
// Ensure a repeatable entity is provided
aBuiltEntity = m_aResHelper.createRepeatableHttpEntity(aBuiltEntity);
}
// Keep the HTTP response status line for external evaluation
final Wrapper<StatusLine> aStatusLineKeeper = new Wrapper<>();
// Keep the HTTP response headers for external evaluation
final HttpHeaderMap aResponseHeaders = new HttpHeaderMap();
final ResponseHandler<T> aRealResponseHandler = x -> {
// Remember the HTTP response data
aStatusLineKeeper.set(x.getStatusLine());
final Header[] aHeaders = x.getAllHeaders();
if (aHeaders != null)
for (final Header aHeader : aHeaders) aResponseHeaders.addHeader(aHeader.getName(), aHeader.getValue());
// Call the original handler
return aResponseHandler.handleResponse(x);
};
final T aResponseContent = m_aHttpPoster.sendGenericMessageWithRetries(sURL, aBuiltHttpHeaders, aBuiltEntity, sMessageID, m_aHttpRetrySettings, aRealResponseHandler, aOutgoingDumper, aRetryCallback);
return new AS4ClientSentMessage<>(aBuiltMsg, aStatusLineKeeper.get(), aResponseHeaders, aResponseContent);
}
use of com.helger.phase4.dump.IAS4OutgoingDumper in project phase4 by phax.
the class AbstractAS4Client method sendMessageAndGetMicroDocument.
@Nullable
public IMicroDocument sendMessageAndGetMicroDocument(@Nonnull final String sURL) throws WSSecurityException, IOException, MessagingException {
final IAS4ClientBuildMessageCallback aCallback = null;
final IAS4OutgoingDumper aOutgoingDumper = null;
final IAS4RetryCallback aRetryCallback = null;
final IMicroDocument ret = sendMessageWithRetries(sURL, new ResponseHandlerMicroDom(), aCallback, aOutgoingDumper, aRetryCallback).getResponse();
AS4HttpDebug.debug(() -> "SEND-RESPONSE received: " + MicroWriter.getNodeAsString(ret, AS4HttpDebug.getDebugXMLWriterSettings()));
return ret;
}
use of com.helger.phase4.dump.IAS4OutgoingDumper in project phase4 by phax.
the class BasicHttpPoster method createDumpingHttpEntity.
@Nonnull
protected static HttpEntity createDumpingHttpEntity(@Nullable final IAS4OutgoingDumper aOutgoingDumper, @Nonnull final HttpEntity aSrcEntity, @Nonnull @Nonempty final String sMessageID, @Nullable final HttpHeaderMap aCustomHttpHeaders, @Nonnegative final int nTry, @Nonnull final Wrapper<OutputStream> aDumpOSHolder) throws IOException {
if (aOutgoingDumper == null) {
// No dumper
return aSrcEntity;
}
// We don't have a message processing state
final OutputStream aDumpOS = aOutgoingDumper.onBeginRequest(EAS4MessageMode.REQUEST, null, null, sMessageID, aCustomHttpHeaders, nTry);
if (aDumpOS == null) {
// No dumping needed
return aSrcEntity;
}
// Otherwise multiple calls to writeTo and getContent would crash
if (!aSrcEntity.isRepeatable())
throw new IllegalStateException("If dumping of outgoing messages is enabled, a repeatable entity must be provided");
// Remember the output stream used for dumping (to be able to close it
// later)
aDumpOSHolder.set(aDumpOS);
if (LOGGER.isDebugEnabled())
LOGGER.debug("Creating dumping entity for the current request");
return new HttpEntityWrapper(aSrcEntity) {
@Override
public void writeTo(@Nonnull @WillNotClose final OutputStream aHttpOS) throws IOException {
// Write to multiple output streams
final MultiOutputStream aMultiOS = new MultiOutputStream(aHttpOS, aDumpOS);
// write to both streams
super.writeTo(aMultiOS);
// Flush both, but do not close both
aMultiOS.flush();
}
};
}
use of com.helger.phase4.dump.IAS4OutgoingDumper in project phase4 by phax.
the class AS4RequestHandler method handleRequest.
/**
* This is the main handling routine when called from an abstract
* (non-Servlet) API
*
* @param aServletRequestIS
* The input stream with the request data. May not be
* <code>null</code>.
* @param aRequestHttpHeaders
* The HTTP headers of the request. May not be <code>null</code>.
* @param aHttpResponse
* The HTTP response to be filled. May not be <code>null</code>.
* @throws Phase4Exception
* in case the request is missing certain prerequisites. Since 0.9.11
* @throws IOException
* In case of IO errors
* @throws MessagingException
* MIME related errors
* @throws WSSecurityException
* In case of WSS4J errors
* @see #handleRequest(InputStream, HttpHeaderMap, IAS4ResponseAbstraction)
* for a more generic API
*/
public void handleRequest(@Nonnull @WillClose final InputStream aServletRequestIS, @Nonnull final HttpHeaderMap aRequestHttpHeaders, @Nonnull final IAS4ResponseAbstraction aHttpResponse) throws Phase4Exception, IOException, MessagingException, WSSecurityException {
final IAS4ParsedMessageCallback aCallback = (aHttpHeaders, aSoapDocument, eSoapVersion, aIncomingAttachments) -> {
// SOAP document and SOAP version are determined
// Collect all runtime errors
final ICommonsList<Ebms3Error> aErrorMessages = new CommonsArrayList<>();
final IAS4ResponseFactory aResponder = _handleSoapMessage(aHttpHeaders, aSoapDocument, eSoapVersion, aIncomingAttachments, aErrorMessages);
if (aResponder != null) {
// Response present -> send back
final IAS4OutgoingDumper aRealOutgoingDumper = m_aOutgoingDumper != null ? m_aOutgoingDumper : AS4DumpManager.getOutgoingDumper();
aResponder.applyToResponse(aHttpResponse, aRealOutgoingDumper);
} else {
// Success, HTTP No Content
aHttpResponse.setStatus(CHttp.HTTP_NO_CONTENT);
}
AS4HttpDebug.debug(() -> "RECEIVE-END with " + (aResponder != null ? "EBMS message" : "no content"));
};
AS4IncomingHandler.parseAS4Message(m_aIAF, m_aResHelper, m_aMessageMetadata, aServletRequestIS, aRequestHttpHeaders, aCallback, m_aIncomingDumper);
}
use of com.helger.phase4.dump.IAS4OutgoingDumper in project phase4 by phax.
the class AS4BidirectionalClientHelper method sendAS4PullRequestAndReceiveAS4UserMessage.
public static void sendAS4PullRequestAndReceiveAS4UserMessage(@Nonnull final IAS4CryptoFactory aCryptoFactory, @Nonnull final IPModeResolver aPModeResolver, @Nonnull final IAS4IncomingAttachmentFactory aIAF, @Nonnull final IAS4IncomingProfileSelector aIncomingProfileSelector, @Nonnull final AS4ClientPullRequestMessage aClientPullRequest, @Nonnull final Locale aLocale, @Nonnull final String sURL, @Nullable final IAS4ClientBuildMessageCallback aBuildMessageCallback, @Nullable final IAS4OutgoingDumper aOutgoingDumper, @Nullable final IAS4IncomingDumper aIncomingDumper, @Nullable final IAS4RetryCallback aRetryCallback, @Nullable final IAS4RawResponseConsumer aResponseConsumer, @Nullable final IAS4UserMessageConsumer aUserMsgConsumer) throws IOException, Phase4Exception, WSSecurityException, MessagingException {
if (LOGGER.isInfoEnabled())
LOGGER.info("Sending AS4 PullRequest to '" + sURL + "' with max. " + aClientPullRequest.httpRetrySettings().getMaxRetries() + " retries");
if (LOGGER.isDebugEnabled())
LOGGER.debug(" MPC = '" + aClientPullRequest.getMPC() + "'");
final Wrapper<HttpResponse> aWrappedResponse = new Wrapper<>();
final ResponseHandler<byte[]> aResponseHdl = aHttpResponse -> {
// May throw an ExtendedHttpResponseException
final HttpEntity aEntity = ResponseHandlerHttpEntity.INSTANCE.handleResponse(aHttpResponse);
if (aEntity == null)
return null;
aWrappedResponse.set(aHttpResponse);
return EntityUtils.toByteArray(aEntity);
};
final AS4ClientSentMessage<byte[]> aResponseEntity = aClientPullRequest.sendMessageWithRetries(sURL, aResponseHdl, aBuildMessageCallback, aOutgoingDumper, aRetryCallback);
if (LOGGER.isInfoEnabled())
LOGGER.info("Successfully transmitted AS4 PullRequest with message ID '" + aResponseEntity.getMessageID() + "' to '" + sURL + "'");
if (aResponseConsumer != null)
aResponseConsumer.handleResponse(aResponseEntity);
// Try interpret result as SignalMessage
if (aResponseEntity.hasResponse() && aResponseEntity.getResponse().length > 0) {
final IAS4IncomingMessageMetadata aMessageMetadata = new AS4IncomingMessageMetadata(EAS4MessageMode.RESPONSE).setRemoteAddr(sURL);
// Read response as EBMS3 User Message
// Read it in any case to ensure signature validation etc. happens
final Ebms3UserMessage aUserMessage = AS4IncomingHandler.parseUserMessage(aCryptoFactory, aPModeResolver, aIAF, aIncomingProfileSelector, aClientPullRequest.getAS4ResourceHelper(), null, aLocale, aMessageMetadata, aWrappedResponse.get(), aResponseEntity.getResponse(), aIncomingDumper);
if (aUserMessage != null && aUserMsgConsumer != null)
aUserMsgConsumer.handleUserMessage(aUserMessage);
} else
LOGGER.info("AS4 ResponseEntity is empty");
}
Aggregations