use of nl.nn.adapterframework.stream.Message in project iaf by ibissource.
the class TimeoutGuardPipe method doPipe.
@Override
public PipeRunResult doPipe(Message message, PipeLineSession session) throws PipeRunException {
ParameterValueList pvl = null;
if (getParameterList() != null) {
try {
pvl = getParameterList().getValues(message, session);
} catch (ParameterException e) {
throw new PipeRunException(this, getLogPrefix(session) + "exception on extracting parameters", e);
}
}
int timeout_work;
String timeout_work_str = getParameterValue(pvl, "timeout");
if (timeout_work_str == null) {
timeout_work = getTimeout();
} else {
timeout_work = Integer.valueOf(timeout_work_str);
}
log.debug(getLogPrefix(session) + "setting timeout of [" + timeout_work + "] s");
TimeoutGuard tg = new TimeoutGuard(timeout_work, getName()) {
@Override
protected void abort() {
// The guard automatically kills the current thread, additional threads maybe 'killed' by implementing killPipe.
killPipe();
}
};
try {
return doPipeWithTimeoutGuarded(message, session);
} catch (Exception e) {
String msg = e.getClass().getName();
if (isThrowException()) {
throw new PipeRunException(this, msg, e);
} else {
String msgString = msg + ": " + e.getMessage();
log.error(msgString, e);
String msgCdataString = "<![CDATA[" + msgString + "]]>";
Message errorMessage = new Message("<error>" + msgCdataString + "</error>");
return new PipeRunResult(getSuccessForward(), errorMessage);
}
} finally {
if (tg.cancel()) {
// Throw a TimeOutException
String msgString = "TimeOutException";
Exception e = new TimeoutException("exceeds timeout of [" + timeout_work + "] s, interupting");
if (isThrowException()) {
throw new PipeRunException(this, msgString, e);
} else {
// This is used for the old console, where a message is displayed
log.error(msgString, e);
String msgCdataString = "<![CDATA[" + msgString + ": " + e.getMessage() + "]]>";
Message errorMessage = new Message("<error>" + msgCdataString + "</error>");
return new PipeRunResult(getSuccessForward(), errorMessage);
}
}
}
}
use of nl.nn.adapterframework.stream.Message in project iaf by ibissource.
the class Receiver method processMessageInAdapter.
/*
* Assumes message is read, and when transacted, transaction is still open.
*/
private Message processMessageInAdapter(Object rawMessageOrWrapper, Message message, String messageId, String technicalCorrelationId, Map<String, Object> threadContext, long waitingDuration, boolean manualRetry, boolean duplicatesAlreadyChecked) throws ListenerException {
long startProcessingTimestamp = System.currentTimeMillis();
// if (message==null) {
// requestSizeStatistics.addValue(0);
// } else {
// requestSizeStatistics.addValue(message.length());
// }
lastMessageDate = startProcessingTimestamp;
log.debug(getLogPrefix() + "received message with messageId [" + messageId + "] (technical) correlationId [" + technicalCorrelationId + "]");
if (StringUtils.isEmpty(messageId)) {
messageId = Misc.createSimpleUUID();
if (log.isDebugEnabled())
log.debug(getLogPrefix() + "generated messageId [" + messageId + "]");
}
if (getChompCharSize() != null || getElementToMove() != null || getElementToMoveChain() != null) {
log.debug(getLogPrefix() + "compact received message");
try {
CompactSaxHandler handler = new CompactSaxHandler();
handler.setChompCharSize(getChompCharSize());
handler.setElementToMove(getElementToMove());
handler.setElementToMoveChain(getElementToMoveChain());
handler.setElementToMoveSessionKey(getElementToMoveSessionKey());
handler.setRemoveCompactMsgNamespaces(isRemoveCompactMsgNamespaces());
handler.setContext(threadContext);
try {
XmlUtils.parseXml(message.asInputSource(), handler);
message = new Message(handler.getXmlString());
} catch (Exception e) {
warn("received message could not be compacted: " + e.getMessage());
}
handler = null;
} catch (Exception e) {
String msg = "error during compacting received message to more compact format";
error(msg, e);
throw new ListenerException(msg, e);
}
}
String businessCorrelationId = null;
if (correlationIDTp != null) {
try {
message.preserve();
businessCorrelationId = correlationIDTp.transform(message, null);
} catch (Exception e) {
// throw new ListenerException(getLogPrefix()+"could not extract businessCorrelationId",e);
log.warn(getLogPrefix() + "could not extract businessCorrelationId");
}
if (StringUtils.isEmpty(businessCorrelationId)) {
String cidText;
if (StringUtils.isNotEmpty(getCorrelationIDXPath())) {
cidText = "xpathExpression [" + getCorrelationIDXPath() + "]";
} else {
cidText = "styleSheet [" + getCorrelationIDStyleSheet() + "]";
}
if (StringUtils.isNotEmpty(technicalCorrelationId)) {
log.info(getLogPrefix() + "did not find correlationId using " + cidText + ", reverting to correlationId of transfer [" + technicalCorrelationId + "]");
businessCorrelationId = technicalCorrelationId;
}
}
} else {
businessCorrelationId = technicalCorrelationId;
}
if (StringUtils.isEmpty(businessCorrelationId) && StringUtils.isNotEmpty(messageId)) {
log.info(getLogPrefix() + "did not find (technical) correlationId, reverting to messageId [" + messageId + "]");
businessCorrelationId = messageId;
}
log.info(getLogPrefix() + "messageId [" + messageId + "] technicalCorrelationId [" + technicalCorrelationId + "] businessCorrelationId [" + businessCorrelationId + "]");
threadContext.put(PipeLineSession.businessCorrelationIdKey, businessCorrelationId);
String label = null;
if (labelTp != null) {
try {
message.preserve();
label = labelTp.transform(message, null);
} catch (Exception e) {
// throw new ListenerException(getLogPrefix()+"could not extract label",e);
log.warn(getLogPrefix() + "could not extract label: (" + ClassUtils.nameOf(e) + ") " + e.getMessage());
}
}
try {
final Message messageFinal = message;
if (!duplicatesAlreadyChecked && hasProblematicHistory(messageId, manualRetry, rawMessageOrWrapper, () -> messageFinal, threadContext, businessCorrelationId)) {
if (!isTransacted()) {
log.warn(getLogPrefix() + "received message with messageId [" + messageId + "] which has a problematic history; aborting processing");
}
numRejected.increase();
setExitState(threadContext, ExitState.REJECTED, 500);
return Message.nullMessage();
}
if (isDuplicateAndSkip(getMessageBrowser(ProcessState.DONE), messageId, businessCorrelationId)) {
setExitState(threadContext, ExitState.SUCCESS, 304);
return Message.nullMessage();
}
if (getCachedProcessResult(messageId) != null) {
numRetried.increase();
}
} catch (Exception e) {
String msg = "exception while checking history";
error(msg, e);
throw wrapExceptionAsListenerException(e);
}
IbisTransaction itx = new IbisTransaction(txManager, getTxDef(), "receiver [" + getName() + "]");
// update processing statistics
// count in processing statistics includes messages that are rolled back to input
startProcessingMessage(waitingDuration);
PipeLineSession pipelineSession = null;
String errorMessage = "";
boolean messageInError = false;
Message result = null;
PipeLineResult pipeLineResult = null;
try {
Message pipelineMessage;
if (getListener() instanceof IBulkDataListener) {
try {
IBulkDataListener<M> bdl = (IBulkDataListener<M>) getListener();
pipelineMessage = new Message(bdl.retrieveBulkData(rawMessageOrWrapper, message, threadContext));
} catch (Throwable t) {
errorMessage = t.getMessage();
messageInError = true;
error("exception retrieving bulk data", t);
ListenerException l = wrapExceptionAsListenerException(t);
throw l;
}
} else {
pipelineMessage = message;
}
numReceived.increase();
// Note: errorMessage is used to pass value from catch-clause to finally-clause!
pipelineSession = createProcessingContext(businessCorrelationId, threadContext, messageId);
// threadContext=pipelineSession; // this is to enable Listeners to use session variables, for instance in afterProcessMessage()
try {
if (getMessageLog() != null) {
getMessageLog().storeMessage(messageId, businessCorrelationId, new Date(), RCV_MESSAGE_LOG_COMMENTS, label, pipelineMessage);
}
log.debug(getLogPrefix() + "preparing TimeoutGuard");
TimeoutGuard tg = new TimeoutGuard("Receiver " + getName());
try {
if (log.isDebugEnabled())
log.debug(getLogPrefix() + "activating TimeoutGuard with transactionTimeout [" + getTransactionTimeout() + "]s");
tg.activateGuard(getTransactionTimeout());
pipeLineResult = adapter.processMessageWithExceptions(businessCorrelationId, pipelineMessage, pipelineSession);
setExitState(threadContext, pipeLineResult.getState(), pipeLineResult.getExitCode());
pipelineSession.put("exitcode", "" + pipeLineResult.getExitCode());
result = pipeLineResult.getResult();
errorMessage = "exitState [" + pipeLineResult.getState() + "], result [";
if (!Message.isEmpty(result) && result.size() > ITransactionalStorage.MAXCOMMENTLEN) {
// Since we can determine the size, assume the message is preserved
errorMessage += result.asString().substring(0, ITransactionalStorage.MAXCOMMENTLEN);
} else {
errorMessage += result;
}
errorMessage += "]";
int status = pipeLineResult.getExitCode();
if (status > 0) {
errorMessage += ", exitcode [" + status + "]";
}
if (log.isDebugEnabled()) {
log.debug(getLogPrefix() + "received result: " + errorMessage);
}
messageInError = itx.isRollbackOnly();
} finally {
log.debug(getLogPrefix() + "canceling TimeoutGuard, isInterrupted [" + Thread.currentThread().isInterrupted() + "]");
if (tg.cancel()) {
errorMessage = "timeout exceeded";
if (Message.isEmpty(result)) {
result = new Message("<timeout/>");
}
messageInError = true;
}
}
if (!messageInError && !isTransacted()) {
messageInError = !pipeLineResult.isSuccessful();
}
} catch (Throwable t) {
if (TransactionSynchronizationManager.isActualTransactionActive()) {
log.debug("<*>" + getLogPrefix() + "TX Update: Received failure, transaction " + (itx.isRollbackOnly() ? "already" : "not yet") + " marked for rollback-only");
}
error("Exception in message processing", t);
errorMessage = t.getMessage();
messageInError = true;
if (pipeLineResult == null) {
pipeLineResult = new PipeLineResult();
}
if (Message.isEmpty(pipeLineResult.getResult())) {
pipeLineResult.setResult(adapter.formatErrorMessage("exception caught", t, message, messageId, this, startProcessingTimestamp));
}
throw wrapExceptionAsListenerException(t);
} finally {
putSessionKeysIntoThreadContext(threadContext, pipelineSession);
}
// }
if (getSender() != null) {
String sendMsg = sendResultToSender(result);
if (sendMsg != null) {
errorMessage = sendMsg;
}
}
} finally {
try {
cacheProcessResult(messageId, errorMessage, new Date(startProcessingTimestamp));
if (!isTransacted() && messageInError && !manualRetry) {
final Message messageFinal = message;
moveInProcessToError(messageId, businessCorrelationId, () -> messageFinal, new Date(startProcessingTimestamp), errorMessage, rawMessageOrWrapper, TXNEW_CTRL);
}
try {
Map<String, Object> afterMessageProcessedMap = threadContext;
if (pipelineSession != null) {
threadContext.putAll(pipelineSession);
}
try {
if (getListener() instanceof IHasProcessState && !itx.isRollbackOnly()) {
ProcessState targetState = messageInError && knownProcessStates.contains(ProcessState.ERROR) ? ProcessState.ERROR : ProcessState.DONE;
changeProcessState(rawMessageOrWrapper, targetState, errorMessage);
}
getListener().afterMessageProcessed(pipeLineResult, rawMessageOrWrapper, afterMessageProcessedMap);
} catch (Exception e) {
if (manualRetry) {
// Somehow messages wrapped in MessageWrapper are in the ITransactionalStorage.
// This might cause class cast exceptions.
// There are, however, also Listeners that might use MessageWrapper as their raw message type,
// like JdbcListener
error("Exception post processing after retry of message messageId [" + messageId + "] cid [" + technicalCorrelationId + "]", e);
} else {
error("Exception post processing message messageId [" + messageId + "] cid [" + technicalCorrelationId + "]", e);
}
throw wrapExceptionAsListenerException(e);
}
} finally {
long finishProcessingTimestamp = System.currentTimeMillis();
finishProcessingMessage(finishProcessingTimestamp - startProcessingTimestamp);
if (!itx.isCompleted()) {
// NB: Spring will take care of executing a commit or a rollback;
// Spring will also ONLY commit the transaction if it was newly created
// by the above call to txManager.getTransaction().
// txManager.commit(txStatus);
itx.commit();
} else {
String msg = "Transaction already completed; we didn't expect this";
warn(msg);
throw new ListenerException(getLogPrefix() + msg);
}
}
} finally {
if (pipelineSession != null) {
if (!Message.isEmpty(result) && result.isScheduledForCloseOnExitOf(pipelineSession)) {
// Don't close Message in case it's passed to a 'parent' adapter or ServiceDispatcher.
log.debug("unscheduling result message from close on exit");
result.unscheduleFromCloseOnExitOf(pipelineSession);
}
pipelineSession.close();
}
}
}
if (log.isDebugEnabled())
log.debug(getLogPrefix() + "messageId [" + messageId + "] correlationId [" + businessCorrelationId + "] returning result [" + result + "]");
return result;
}
use of nl.nn.adapterframework.stream.Message in project iaf by ibissource.
the class Receiver method moveInProcessToError.
public void moveInProcessToError(String originalMessageId, String correlationId, ThrowingSupplier<Message, ListenerException> messageSupplier, Date receivedDate, String comments, Object rawMessage, TransactionDefinition txDef) {
if (getListener() instanceof IHasProcessState) {
ProcessState targetState = knownProcessStates.contains(ProcessState.ERROR) ? ProcessState.ERROR : ProcessState.DONE;
try {
changeProcessState(rawMessage, targetState, comments);
} catch (ListenerException e) {
log.error(getLogPrefix() + "Could not set process state to ERROR", e);
}
}
ISender errorSender = getErrorSender();
ITransactionalStorage<Serializable> errorStorage = getErrorStorage();
if (errorSender == null && errorStorage == null && knownProcessStates().isEmpty()) {
log.debug(getLogPrefix() + "has no errorSender, errorStorage or knownProcessStates, will not move message with id [" + originalMessageId + "] correlationId [" + correlationId + "] to errorSender/errorStorage");
return;
}
throwEvent(RCV_MESSAGE_TO_ERRORSTORE_EVENT);
log.debug(getLogPrefix() + "moves message with id [" + originalMessageId + "] correlationId [" + correlationId + "] to errorSender/errorStorage");
TransactionStatus txStatus = null;
try {
txStatus = txManager.getTransaction(txDef);
} catch (Exception e) {
log.error(getLogPrefix() + "Exception preparing to move input message with id [" + originalMessageId + "] to error sender", e);
// no use trying again to send message on errorSender, will cause same exception!
return;
}
Message message = null;
try {
if (errorSender != null) {
message = messageSupplier.get();
errorSender.sendMessage(message, null);
}
if (errorStorage != null) {
Serializable sobj;
if (rawMessage == null) {
if (message == null) {
message = messageSupplier.get();
}
if (message.isBinary()) {
sobj = message.asByteArray();
} else {
sobj = message.asString();
}
} else {
if (rawMessage instanceof Serializable) {
sobj = (Serializable) rawMessage;
} else {
try {
sobj = new MessageWrapper(rawMessage, getListener());
} catch (ListenerException e) {
log.error(getLogPrefix() + "could not wrap non serializable message for messageId [" + originalMessageId + "]", e);
if (message == null) {
message = messageSupplier.get();
}
sobj = message;
}
}
}
errorStorage.storeMessage(originalMessageId, correlationId, receivedDate, comments, null, sobj);
}
txManager.commit(txStatus);
} catch (Exception e) {
log.error(getLogPrefix() + "Exception moving message with id [" + originalMessageId + "] correlationId [" + correlationId + "] to error sender or error storage, original message: [" + message + "]", e);
try {
if (!txStatus.isCompleted()) {
txManager.rollback(txStatus);
}
} catch (Exception rbe) {
log.error(getLogPrefix() + "Exception while rolling back transaction for message with id [" + originalMessageId + "] correlationId [" + correlationId + "], original message: [" + message + "]", rbe);
}
}
}
use of nl.nn.adapterframework.stream.Message in project iaf by ibissource.
the class PutInSession method doPipe.
@Override
public PipeRunResult doPipe(Message message, PipeLineSession session) throws PipeRunException {
if (StringUtils.isNotEmpty(getSessionKey())) {
Message v;
if (getValue() == null) {
try {
message.preserve();
} catch (IOException e) {
throw new PipeRunException(this, getLogPrefix(session) + "cannot preserve message", e);
}
v = message;
} else {
v = Message.asMessage(getValue());
}
session.put(getSessionKey(), v);
if (log.isDebugEnabled())
log.debug(getLogPrefix(session) + "stored [" + v + "] in pipeLineSession under key [" + getSessionKey() + "]");
}
ParameterList parameterList = getParameterList();
if (!parameterList.isEmpty()) {
try {
ParameterValueList pvl = parameterList.getValues(message, session, isNamespaceAware());
if (pvl != null) {
for (ParameterValue pv : pvl) {
String name = pv.getName();
Object value = pv.getValue();
session.put(name, value);
if (log.isDebugEnabled())
log.debug(getLogPrefix(session) + "stored [" + value + "] in pipeLineSession under key [" + name + "]");
}
}
} catch (ParameterException e) {
throw new PipeRunException(this, getLogPrefix(session) + "exception extracting parameters", e);
}
}
return new PipeRunResult(getSuccessForward(), message);
}
use of nl.nn.adapterframework.stream.Message in project iaf by ibissource.
the class ServiceJob method execute.
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
log.info("executing" + getLogPrefix(context));
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
String serviceName = dataMap.getString(JAVALISTENER_KEY);
Message message = new Message(dataMap.getString(MESSAGE_KEY));
// send job
IbisLocalSender localSender = new IbisLocalSender();
localSender.setJavaListener(serviceName);
localSender.setIsolated(false);
localSender.setName("ServiceJob");
localSender.configure();
localSender.open();
try {
localSender.sendMessage(message, null);
} finally {
localSender.close();
}
} catch (Exception e) {
log.error("JobExecutionException while running " + getLogPrefix(context), e);
throw new JobExecutionException(e, false);
}
log.debug(getLogPrefix(context) + "completed");
}
Aggregations