Search in sources :

Example 21 with PipeLineSession

use of nl.nn.adapterframework.core.PipeLineSession in project iaf by ibissource.

the class PushingJmsListener method afterMessageProcessed.

@Override
public void afterMessageProcessed(PipeLineResult plr, Object rawMessageOrWrapper, Map<String, Object> threadContext) throws ListenerException {
    String cid = (String) threadContext.get(PipeLineSession.technicalCorrelationIdKey);
    // session is/must be saved in threadcontext by JmsConnector
    Session session = (Session) threadContext.get(IListenerConnector.THREAD_CONTEXT_SESSION_KEY);
    if (log.isDebugEnabled())
        log.debug(getLogPrefix() + "in PushingJmsListener.afterMessageProcessed()");
    try {
        Destination replyTo = (Destination) threadContext.get("replyTo");
        // handle reply
        if (isUseReplyTo() && (replyTo != null)) {
            log.debug(getLogPrefix() + "sending reply message with correlationID[" + cid + "], replyTo [" + replyTo.toString() + "]");
            long timeToLive = getReplyMessageTimeToLive();
            boolean ignoreInvalidDestinationException = false;
            if (timeToLive == 0) {
                if (rawMessageOrWrapper instanceof javax.jms.Message) {
                    javax.jms.Message messageReceived = (javax.jms.Message) rawMessageOrWrapper;
                    long expiration = messageReceived.getJMSExpiration();
                    if (expiration != 0) {
                        timeToLive = expiration - new Date().getTime();
                        if (timeToLive <= 0) {
                            log.warn(getLogPrefix() + "message [" + cid + "] expired [" + timeToLive + "]ms, sending response with 1 second time to live");
                            timeToLive = 1000;
                            // In case of a temporary queue it might already
                            // have disappeared.
                            ignoreInvalidDestinationException = true;
                        }
                    }
                } else {
                    log.warn(getLogPrefix() + "message with correlationID [" + cid + "] is not a JMS message, but [" + rawMessageOrWrapper.getClass().getName() + "], cannot determine time to live [" + timeToLive + "]ms, sending response with 20 second time to live");
                    timeToLive = 1000;
                    ignoreInvalidDestinationException = true;
                }
            }
            Map<String, Object> properties = getMessageProperties(threadContext);
            send(session, replyTo, cid, prepareReply(plr.getResult(), threadContext), getReplyMessageType(), timeToLive, getReplyDeliveryMode().getDeliveryMode(), getReplyPriority(), ignoreInvalidDestinationException, properties);
        } else {
            if (getSender() == null) {
                log.info("[" + getName() + "] has no sender, not sending the result.");
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("[" + getName() + "] no replyTo address found or not configured to use replyTo, using default destination sending message with correlationID[" + cid + "] [" + plr.getResult() + "]");
                }
                PipeLineSession pipeLineSession = new PipeLineSession();
                pipeLineSession.put(PipeLineSession.messageIdKey, cid);
                getSender().sendMessage(plr.getResult(), pipeLineSession);
            }
        }
        // commit, but no rollback).
        if (plr != null && !isTransacted() && isJmsTransacted() && plr.getState() == ExitState.SUCCESS) {
            if (session == null) {
                log.error(getLogPrefix() + "session is null, cannot roll back session");
            } else {
                log.warn(getLogPrefix() + "got exit state [" + plr.getState() + "], rolling back session");
                session.rollback();
            }
        }
    } catch (Exception e) {
        if (e instanceof ListenerException) {
            throw (ListenerException) e;
        }
        throw new ListenerException(e);
    }
}
Also used : Destination(javax.jms.Destination) PipeLineSession(nl.nn.adapterframework.core.PipeLineSession) Date(java.util.Date) ConfigurationException(nl.nn.adapterframework.configuration.ConfigurationException) ListenerException(nl.nn.adapterframework.core.ListenerException) ListenerException(nl.nn.adapterframework.core.ListenerException) PipeLineSession(nl.nn.adapterframework.core.PipeLineSession) Session(javax.jms.Session)

Example 22 with PipeLineSession

use of nl.nn.adapterframework.core.PipeLineSession 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;
}
Also used : Message(nl.nn.adapterframework.stream.Message) PipeLineSession(nl.nn.adapterframework.core.PipeLineSession) TimeoutGuard(nl.nn.adapterframework.task.TimeoutGuard) TimeoutException(nl.nn.adapterframework.core.TimeoutException) SenderException(nl.nn.adapterframework.core.SenderException) ListenerException(nl.nn.adapterframework.core.ListenerException) ConfigurationException(nl.nn.adapterframework.configuration.ConfigurationException) Date(java.util.Date) IHasProcessState(nl.nn.adapterframework.core.IHasProcessState) ProcessState(nl.nn.adapterframework.core.ProcessState) ListenerException(nl.nn.adapterframework.core.ListenerException) IBulkDataListener(nl.nn.adapterframework.core.IBulkDataListener) CompactSaxHandler(nl.nn.adapterframework.util.CompactSaxHandler) IHasProcessState(nl.nn.adapterframework.core.IHasProcessState) IbisTransaction(nl.nn.adapterframework.core.IbisTransaction) PipeLineResult(nl.nn.adapterframework.core.PipeLineResult) INamedObject(nl.nn.adapterframework.core.INamedObject)

Example 23 with PipeLineSession

use of nl.nn.adapterframework.core.PipeLineSession in project iaf by ibissource.

the class FileSystemActorExtraTest method fileSystemActorAppendActionWithDailyRollover.

@Test
public void fileSystemActorAppendActionWithDailyRollover() throws Exception {
    String filename = "rolloverDaily" + FILE1;
    String contents = "thanos car ";
    int numOfBackups = 12;
    int numOfWrites = 10;
    Date currentDate = new Date();
    Date firstDate;
    long millisPerDay = 1000L * 60L * 60L * 24L;
    if (_fileExists(filename)) {
        _deleteFile(null, filename);
    }
    createFile(null, filename, "thanos car ");
    setFileDate(null, filename, firstDate = new Date(currentDate.getTime() - (millisPerDay * numOfWrites)));
    PipeLineSession session = new PipeLineSession();
    ParameterList params = new ParameterList();
    params.add(ParameterBuilder.create().withName("contents").withSessionKey("appendActionwString"));
    params.configure();
    actor.setAction(FileSystemAction.APPEND);
    actor.setRotateDays(numOfBackups);
    actor.configure(fileSystem, params, owner);
    actor.open();
    Message message = new Message(filename);
    for (int i = 0; i < numOfWrites; i++) {
        setFileDate(null, filename, new Date(firstDate.getTime() + (millisPerDay * i)));
        session.put("appendActionwString", contents + i);
        ParameterValueList pvl = params.getValues(message, session);
        String result = (String) actor.doAction(message, pvl, null);
        TestAssertions.assertXpathValueEquals(filename, result, "file/@name");
    }
    for (int i = 1; i <= numOfWrites - 1; i++) {
        String formattedDate = DateUtils.format(new Date(firstDate.getTime() + (millisPerDay * i)), DateUtils.shortIsoFormat);
        String actualContentsi = readFile(null, filename + "." + formattedDate);
        assertEquals((contents + (i - 1)).trim(), actualContentsi.trim());
    }
}
Also used : ParameterValueList(nl.nn.adapterframework.parameters.ParameterValueList) Message(nl.nn.adapterframework.stream.Message) PipeLineSession(nl.nn.adapterframework.core.PipeLineSession) ParameterList(nl.nn.adapterframework.parameters.ParameterList) Date(java.util.Date) Test(org.junit.Test)

Example 24 with PipeLineSession

use of nl.nn.adapterframework.core.PipeLineSession in project iaf by ibissource.

the class FileSystemPipeTest method fileSystemPipeUploadActionTestWithInputStream.

@Test
public void fileSystemPipeUploadActionTestWithInputStream() throws Exception {
    String filename = "uploadedwithInputStream" + FILE1;
    String contents = "Some text content to test upload action\n";
    if (_fileExists(filename)) {
        _deleteFile(null, filename);
    }
    InputStream stream = new ByteArrayInputStream(contents.getBytes("UTF-8"));
    PipeLineSession session = new PipeLineSession();
    session.put("uploadActionTarget", stream);
    fileSystemPipe.addParameter(ParameterBuilder.create().withName("file").withSessionKey("uploadActionTarget"));
    fileSystemPipe.setAction(FileSystemAction.UPLOAD);
    fileSystemPipe.configure();
    fileSystemPipe.start();
    Message message = new Message(filename);
    PipeRunResult prr = fileSystemPipe.doPipe(message, session);
    String result = prr.getResult().asString();
    TestAssertions.assertXpathValueEquals(filename, result, "file/@name");
    waitForActionToFinish();
    String actual = readFile(null, filename);
    // test
    // TODO: evaluate 'result'
    // assertEquals("result of sender should be input message",result,message);
    assertEquals(contents.trim(), actual.trim());
}
Also used : PipeRunResult(nl.nn.adapterframework.core.PipeRunResult) Message(nl.nn.adapterframework.stream.Message) ByteArrayInputStream(java.io.ByteArrayInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) PipeLineSession(nl.nn.adapterframework.core.PipeLineSession) Test(org.junit.Test)

Example 25 with PipeLineSession

use of nl.nn.adapterframework.core.PipeLineSession in project iaf by ibissource.

the class FileSystemPipeTest method fileSystemPipeUploadActionTestWithByteArray.

@Test
public void fileSystemPipeUploadActionTestWithByteArray() throws Exception {
    String filename = "uploadedwithByteArray" + FILE1;
    String contents = "Some text content to test upload action\n";
    if (_fileExists(filename)) {
        _deleteFile(null, filename);
    }
    PipeLineSession session = new PipeLineSession();
    session.put("uploadActionTargetwByteArray", contents.getBytes());
    fileSystemPipe.addParameter(ParameterBuilder.create().withName("file").withSessionKey("uploadActionTargetwByteArray"));
    fileSystemPipe.setAction(FileSystemAction.UPLOAD);
    fileSystemPipe.configure();
    fileSystemPipe.start();
    Message message = new Message(filename);
    PipeRunResult prr = fileSystemPipe.doPipe(message, session);
    String result = prr.getResult().asString();
    TestAssertions.assertXpathValueEquals(filename, result, "file/@name");
    waitForActionToFinish();
    String actual = readFile(null, filename);
    // test
    // TODO: evaluate 'result'
    // assertEquals("result of sender should be input message",result,message);
    assertEquals(contents.trim(), actual.trim());
}
Also used : PipeRunResult(nl.nn.adapterframework.core.PipeRunResult) Message(nl.nn.adapterframework.stream.Message) PipeLineSession(nl.nn.adapterframework.core.PipeLineSession) Test(org.junit.Test)

Aggregations

PipeLineSession (nl.nn.adapterframework.core.PipeLineSession)270 Message (nl.nn.adapterframework.stream.Message)210 Test (org.junit.Test)202 SenderException (nl.nn.adapterframework.core.SenderException)43 PipeRunResult (nl.nn.adapterframework.core.PipeRunResult)33 UrlMessage (nl.nn.adapterframework.stream.UrlMessage)30 ByteArrayInputStream (java.io.ByteArrayInputStream)26 IOException (java.io.IOException)25 Parameter (nl.nn.adapterframework.parameters.Parameter)23 PipeForward (nl.nn.adapterframework.core.PipeForward)21 ParameterValueList (nl.nn.adapterframework.parameters.ParameterValueList)17 Date (java.util.Date)15 ConfigurationException (nl.nn.adapterframework.configuration.ConfigurationException)14 InputStream (java.io.InputStream)11 TimeoutException (nl.nn.adapterframework.core.TimeoutException)11 ParameterList (nl.nn.adapterframework.parameters.ParameterList)11 Map (java.util.Map)10 SimpleDateFormat (java.text.SimpleDateFormat)9 SOAPMessage (javax.xml.soap.SOAPMessage)9 URL (java.net.URL)8