public void process(Exchange exchange) throws Exception { if (executor == null) { executor = exchange .getContext() .getExecutorServiceManager() .newFixedThreadPool(this, "CLAIM-CHECK", 4); } String id = tag.evaluate(exchange, String.class); exchange.setProperty(ClaimCheck.CLAIMCHECK_TAG_HEADER, id); final Producer conveyor = findDestination(exchange).createProducer(); final Exchange baggage = ExchangeHelper.createCorrelatedCopy(exchange, false); LOG.info("Checking in 'baggage'"); executor.submit( new Callable<Exchange>() { public Exchange call() throws Exception { try { LOG.debug("[claimcheck] {} {}", conveyor, baggage); conveyor.process(baggage); } catch (Throwable e) { LOG.warn( "Error occurred during processing " + baggage + " checked in at " + conveyor, e); } return baggage; }; }); LOG.info("Continue normal flow without 'baggage'"); Message out = exchange.getOut(); out.setBody(value.evaluate(exchange, Object.class)); }
/** Evaluate using classic parameter binding using the pre compute expression */ private Object evaluateParameterBinding( Exchange exchange, Expression expression, int index, Class<?> parameterType) { Object answer = null; // use object first to avoid type conversion so we know if there is a value or not Object result = expression.evaluate(exchange, Object.class); if (result != null) { try { if (parameterType.isInstance(result)) { // optimize if the value is already the same type answer = result; } else { // we got a value now try to convert it to the expected type answer = exchange.getContext().getTypeConverter().mandatoryConvertTo(parameterType, result); } if (LOG.isTraceEnabled()) { LOG.trace( "Parameter #{} evaluated as: {} type: ", new Object[] {index, answer, ObjectHelper.type(answer)}); } } catch (NoTypeConversionAvailableException e) { if (LOG.isDebugEnabled()) { LOG.debug( "Cannot convert from type: {} to type: {} for parameter #{}", new Object[] {ObjectHelper.type(result), parameterType, index}); } throw new ParameterBindingException(e, method, index, parameterType, result); } } else { LOG.trace("Parameter #{} evaluated as null", index); } return answer; }
@Override public Object convert( Object existingDestinationFieldValue, Object sourceFieldValue, Class<?> destinationClass, Class<?> sourceClass) { try { if (currentExchange.get() == null) { throw new IllegalStateException("Current exchange has not been set for ExpressionMapper"); } Expression exp; // Resolve the language being used for this expression and evaluate Exchange exchange = currentExchange.get(); Language expLang = exchange.getContext().resolveLanguage(getLanguagePart()); String scheme = getSchemePart(); if (scheme != null && (scheme.equalsIgnoreCase("classpath") || scheme.equalsIgnoreCase("file") || scheme.equalsIgnoreCase("http"))) { String path = getPathPart(); try { exp = expLang.createExpression(resolveScript(scheme + ":" + path)); } catch (IOException e) { throw new IllegalStateException("Expression script specified but not found", e); } } else { exp = expLang.createExpression(getExpressionPart()); } return exp.evaluate(exchange, destinationClass); } finally { done(); } }
@Override public boolean process(Exchange exchange, AsyncCallback callback) { // use atomic integer to be able to pass reference and keep track on the values AtomicInteger index = new AtomicInteger(); AtomicInteger count = new AtomicInteger(); // Intermediate conversion to String is needed when direct conversion to Integer is not // available // but evaluation result is a textual representation of a numeric value. String text = expression.evaluate(exchange, String.class); try { int num = ExchangeHelper.convertToMandatoryType(exchange, Integer.class, text); count.set(num); } catch (NoTypeConversionAvailableException e) { exchange.setException(e); callback.done(true); return true; } // we hold on to the original Exchange in case it's needed for copies final Exchange original = exchange; // per-iteration exchange Exchange target = exchange; // set the size before we start exchange.setProperty(Exchange.LOOP_SIZE, count); // loop synchronously while (index.get() < count.get()) { // and prepare for next iteration // if (!copy) target = exchange; else copy of original target = prepareExchange(exchange, index.get(), original); boolean sync = process(target, callback, index, count, original); if (!sync) { LOG.trace( "Processing exchangeId: {} is continued being processed asynchronously", target.getExchangeId()); // the remainder of the routing slip will be completed async // so we break out now, then the callback will be invoked which then continue routing from // where we left here return false; } LOG.trace( "Processing exchangeId: {} is continued being processed synchronously", target.getExchangeId()); // increment counter before next loop index.getAndIncrement(); } // we are done so prepare the result ExchangeHelper.copyResults(exchange, target); LOG.trace("Processing complete for exchangeId: {} >>> {}", exchange.getExchangeId(), exchange); callback.done(true); return true; }
public void testCamelContextPropertiesExpression() throws Exception { camelContext.getProperties().put("CamelTestKey", "CamelTestValue"); Expression expression = camelContextPropertyExpression("CamelTestKey"); assertExpression(expression, exchange, "CamelTestValue"); expression = camelContextPropertiesExpression(); Map<?, ?> properties = expression.evaluate(exchange, Map.class); assertEquals("Get a wrong properties size", properties.size(), 1); }
@Override public boolean process(Exchange exchange, AsyncCallback callback) { try { Object newBody = expression.evaluate(exchange, Object.class); if (exchange.getException() != null) { // the expression threw an exception so we should break-out callback.done(true); return true; } boolean out = exchange.hasOut(); Message old = out ? exchange.getOut() : exchange.getIn(); // create a new message container so we do not drag specialized message objects along // but that is only needed if the old message is a specialized message boolean copyNeeded = !(old.getClass().equals(DefaultMessage.class)); if (copyNeeded) { Message msg = new DefaultMessage(); msg.copyFrom(old); msg.setBody(newBody); // replace message on exchange ExchangeHelper.replaceMessage(exchange, msg, false); } else { // no copy needed so set replace value directly old.setBody(newBody); } } catch (Throwable e) { exchange.setException(e); } callback.done(true); return true; }
public String createFileName(Exchange exchange) { String answer; // overrule takes precedence Object value; Object overrule = exchange.getIn().getHeader(Exchange.OVERRULE_FILE_NAME); if (overrule != null) { if (overrule instanceof Expression) { value = overrule; } else { value = exchange.getContext().getTypeConverter().convertTo(String.class, exchange, overrule); } } else { value = exchange.getIn().getHeader(Exchange.FILE_NAME); } // if we have an overrule then override the existing header to use the overrule computed name // from this point forward if (overrule != null) { exchange.getIn().setHeader(Exchange.FILE_NAME, value); } if (value != null && value instanceof String && StringHelper.hasStartToken((String) value, "simple")) { log.warn( "Simple expression: {} detected in header: {} of type String. This feature has been removed (see CAMEL-6748).", value, Exchange.FILE_NAME); } // expression support Expression expression = endpoint.getFileName(); if (value != null && value instanceof Expression) { expression = (Expression) value; } // evaluate the name as a String from the value String name; if (expression != null) { log.trace("Filename evaluated as expression: {}", expression); name = expression.evaluate(exchange, String.class); } else { name = exchange.getContext().getTypeConverter().convertTo(String.class, exchange, value); } // flatten name if (name != null && endpoint.isFlatten()) { // check for both windows and unix separators int pos = Math.max(name.lastIndexOf("/"), name.lastIndexOf("\\")); if (pos != -1) { name = name.substring(pos + 1); } } // compute path by adding endpoint starting directory String endpointPath = endpoint.getConfiguration().getDirectory(); String baseDir = ""; if (endpointPath.length() > 0) { // Its a directory so we should use it as a base path for the filename // If the path isn't empty, we need to add a trailing / if it isn't already there baseDir = endpointPath; boolean trailingSlash = endpointPath.endsWith("/") || endpointPath.endsWith("\\"); if (!trailingSlash) { baseDir += getFileSeparator(); } } if (name != null) { answer = baseDir + name; } else { // use a generated filename if no name provided answer = baseDir + endpoint.getGeneratedFileName(exchange.getIn()); } if (endpoint.getConfiguration().needToNormalize()) { // must normalize path to cater for Windows and other OS answer = normalizePath(answer); } return answer; }
/** * Evaluate using parameter values where the values can be provided in the method name syntax. * * <p>This methods returns accordingly: * * <ul> * <li><tt>null</tt> - if not a parameter value * <li><tt>Void.TYPE</tt> - if an explicit null, forcing Camel to pass in <tt>null</tt> for * that given parameter * <li>a non <tt>null</tt> value - if the parameter was a parameter value, and to be used * </ul> * * @since 2.9 */ private Object evaluateParameterValue( Exchange exchange, int index, Object parameterValue, Class<?> parameterType) { Object answer = null; // convert the parameter value to a String String exp = exchange .getContext() .getTypeConverter() .convertTo(String.class, exchange, parameterValue); if (exp != null) { // check if its a valid parameter value boolean valid = BeanHelper.isValidParameterValue(exp); if (!valid) { // it may be a parameter type instead, and if so, then we should return null, // as this method is only for evaluating parameter values Boolean isClass = BeanHelper.isAssignableToExpectedType( exchange.getContext().getClassResolver(), exp, parameterType); // the method will return a non null value if exp is a class if (isClass != null) { return null; } } // use simple language to evaluate the expression, as it may use the simple language to // refer to message body, headers etc. Expression expression = null; try { expression = exchange.getContext().resolveLanguage("simple").createExpression(exp); parameterValue = expression.evaluate(exchange, Object.class); // use "null" to indicate the expression returned a null value which is a valid response // we need to honor if (parameterValue == null) { parameterValue = "null"; } } catch (Exception e) { throw new ExpressionEvaluationException( expression, "Cannot create/evaluate simple expression: " + exp + " to be bound to parameter at index: " + index + " on method: " + getMethod(), exchange, e); } // special for explicit null parameter values (as end users can explicit indicate they want // null as parameter) // see method javadoc for details if ("null".equals(parameterValue)) { return Void.TYPE; } // the parameter value may match the expected type, then we use it as-is if (parameterType.isAssignableFrom(parameterValue.getClass())) { valid = true; } else { // the parameter value was not already valid, but since the simple language have evaluated // the expression // which may change the parameterValue, so we have to check it again to see if its now // valid exp = exchange.getContext().getTypeConverter().tryConvertTo(String.class, parameterValue); // String values from the simple language is always valid if (!valid) { // re validate if the parameter was not valid the first time (String values should be // accepted) valid = parameterValue instanceof String || BeanHelper.isValidParameterValue(exp); } } if (valid) { // we need to unquote String parameters, as the enclosing quotes is there to denote a // parameter value if (parameterValue instanceof String) { parameterValue = StringHelper.removeLeadingAndEndingQuotes((String) parameterValue); } if (parameterValue != null) { try { // its a valid parameter value, so convert it to the expected type of the parameter answer = exchange .getContext() .getTypeConverter() .mandatoryConvertTo(parameterType, exchange, parameterValue); if (LOG.isTraceEnabled()) { LOG.trace( "Parameter #{} evaluated as: {} type: ", new Object[] {index, answer, ObjectHelper.type(answer)}); } } catch (Exception e) { if (LOG.isDebugEnabled()) { LOG.debug( "Cannot convert from type: {} to type: {} for parameter #{}", new Object[] {ObjectHelper.type(parameterValue), parameterType, index}); } throw new ParameterBindingException(e, method, index, parameterType, parameterValue); } } } } return answer; }
public MethodInvocation createMethodInvocation(final Object pojo, final Exchange exchange) { final Object[] arguments = parametersExpression.evaluate(exchange, Object[].class); return new MethodInvocation() { public Method getMethod() { return method; } public Object[] getArguments() { return arguments; } public boolean proceed(AsyncCallback callback) { Object body = exchange.getIn().getBody(); if (body != null && body instanceof StreamCache) { // ensure the stream cache is reset before calling the method ((StreamCache) body).reset(); } try { return doProceed(callback); } catch (InvocationTargetException e) { exchange.setException(e.getTargetException()); callback.done(true); return true; } catch (Throwable e) { exchange.setException(e); callback.done(true); return true; } } private boolean doProceed(AsyncCallback callback) throws Exception { // dynamic router should be invoked beforehand if (dynamicRouter != null) { if (!dynamicRouter.isStarted()) { ServiceHelper.startService(dynamicRouter); } // use a expression which invokes the method to be used by dynamic router Expression expression = new DynamicRouterExpression(pojo); return dynamicRouter.doRoutingSlip(exchange, expression, callback); } // invoke pojo if (LOG.isTraceEnabled()) { LOG.trace( ">>>> invoking: {} on bean: {} with arguments: {} for exchange: {}", new Object[] {method, pojo, asString(arguments), exchange}); } Object result = invoke(method, pojo, arguments, exchange); if (recipientList != null) { // ensure its started if (!recipientList.isStarted()) { ServiceHelper.startService(recipientList); } return recipientList.sendToRecipientList(exchange, result, callback); } if (routingSlip != null) { if (!routingSlip.isStarted()) { ServiceHelper.startService(routingSlip); } return routingSlip.doRoutingSlip(exchange, result, callback); } // If it's Java 8 async result if (CompletionStage.class.isAssignableFrom(getMethod().getReturnType())) { CompletionStage<?> completionStage = (CompletionStage<?>) result; completionStage.whenComplete( (resultObject, e) -> { if (e != null) { exchange.setException(e); } else if (resultObject != null) { fillResult(exchange, resultObject); } callback.done(false); }); return false; } // if the method returns something then set the value returned on the Exchange if (!getMethod().getReturnType().equals(Void.TYPE) && result != Void.TYPE) { fillResult(exchange, result); } // we did not use any of the eips, but just invoked the bean // so notify the callback we are done synchronously callback.done(true); return true; } public Object getThis() { return pojo; } public AccessibleObject getStaticPart() { return method; } }; }
public <T> T evaluate(Exchange exchange, Class<T> type) { if (expression == null) { expression = createExpression(exchange); } return expression.evaluate(exchange, type); }
/** * Enriches the input data (<code>exchange</code>) by first obtaining additional data from an * endpoint represented by an endpoint <code>producer</code> and second by aggregating input data * and additional data. Aggregation of input data and additional data is delegated to an {@link * org.apache.camel.processor.aggregate.AggregationStrategy} object set at construction time. If * the message exchange with the resource endpoint fails then no aggregation will be done and the * failed exchange content is copied over to the original message exchange. * * @param exchange input data. */ @Override public boolean process(Exchange exchange, AsyncCallback callback) { try { preCheckPoll(exchange); } catch (Exception e) { exchange.setException(new CamelExchangeException("Error during pre poll check", exchange, e)); callback.done(true); return true; } // which consumer to use PollingConsumer consumer; Endpoint endpoint; // use dynamic endpoint so calculate the endpoint to use Object recipient = null; try { recipient = expression.evaluate(exchange, Object.class); endpoint = resolveEndpoint(exchange, recipient); // acquire the consumer from the cache consumer = consumerCache.acquirePollingConsumer(endpoint); } catch (Throwable e) { if (isIgnoreInvalidEndpoint()) { if (LOG.isDebugEnabled()) { LOG.debug( "Endpoint uri is invalid: " + recipient + ". This exception will be ignored.", e); } } else { exchange.setException(e); } callback.done(true); return true; } Exchange resourceExchange; try { if (timeout < 0) { LOG.debug("Consumer receive: {}", consumer); resourceExchange = consumer.receive(); } else if (timeout == 0) { LOG.debug("Consumer receiveNoWait: {}", consumer); resourceExchange = consumer.receiveNoWait(); } else { LOG.debug("Consumer receive with timeout: {} ms. {}", timeout, consumer); resourceExchange = consumer.receive(timeout); } if (resourceExchange == null) { LOG.debug("Consumer received no exchange"); } else { LOG.debug("Consumer received: {}", resourceExchange); } } catch (Exception e) { exchange.setException(new CamelExchangeException("Error during poll", exchange, e)); callback.done(true); return true; } finally { // return the consumer back to the cache consumerCache.releasePollingConsumer(endpoint, consumer); } try { if (!isAggregateOnException() && (resourceExchange != null && resourceExchange.isFailed())) { // copy resource exchange onto original exchange (preserving pattern) copyResultsPreservePattern(exchange, resourceExchange); } else { prepareResult(exchange); // prepare the exchanges for aggregation ExchangeHelper.prepareAggregation(exchange, resourceExchange); // must catch any exception from aggregation Exchange aggregatedExchange = aggregationStrategy.aggregate(exchange, resourceExchange); if (aggregatedExchange != null) { // copy aggregation result onto original exchange (preserving pattern) copyResultsPreservePattern(exchange, aggregatedExchange); // handover any synchronization if (resourceExchange != null) { resourceExchange.handoverCompletions(exchange); } } } // set header with the uri of the endpoint enriched so we can use that for tracing etc if (exchange.hasOut()) { exchange.getOut().setHeader(Exchange.TO_ENDPOINT, consumer.getEndpoint().getEndpointUri()); } else { exchange.getIn().setHeader(Exchange.TO_ENDPOINT, consumer.getEndpoint().getEndpointUri()); } } catch (Throwable e) { exchange.setException( new CamelExchangeException("Error occurred during aggregation", exchange, e)); callback.done(true); return true; } callback.done(true); return true; }