INT-4386: Support Instant in schedule expressions
JIRA: https://jira.spring.io/browse/INT-4386 * Expose `java.time` in the `IntegrationEvaluationContextFactoryBean` ot simply a `T()` SpEL operator * Add `Instant` result evaluation to the `delayExpression`
This commit is contained in:
committed by
Gary Russell
parent
020ea76d59
commit
f901c4e167
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,6 +26,7 @@ import org.springframework.expression.BeanResolver;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypeLocator;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeLocator;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
|
||||
/**
|
||||
@@ -65,7 +66,7 @@ import org.springframework.integration.context.IntegrationContextUtils;
|
||||
public class IntegrationEvaluationContextFactoryBean extends AbstractEvaluationContextFactoryBean
|
||||
implements FactoryBean<StandardEvaluationContext> {
|
||||
|
||||
private volatile TypeLocator typeLocator;
|
||||
private TypeLocator typeLocator;
|
||||
|
||||
private BeanResolver beanResolver;
|
||||
|
||||
@@ -87,12 +88,21 @@ public class IntegrationEvaluationContextFactoryBean extends AbstractEvaluationC
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandardEvaluationContext getObject() throws Exception {
|
||||
public StandardEvaluationContext getObject() {
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
|
||||
if (this.typeLocator != null) {
|
||||
evaluationContext.setTypeLocator(this.typeLocator);
|
||||
}
|
||||
|
||||
TypeLocator typeLocator = evaluationContext.getTypeLocator();
|
||||
if (typeLocator instanceof StandardTypeLocator) {
|
||||
/*
|
||||
* Register the 'java.time' package so its classes don't need a FQCN,
|
||||
* for example ' T(Instant).now().plusSeconds(5)'.
|
||||
*/
|
||||
((StandardTypeLocator) typeLocator).registerImport("java.time");
|
||||
}
|
||||
|
||||
evaluationContext.setBeanResolver(this.beanResolver);
|
||||
evaluationContext.setTypeConverter(getTypeConverter());
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.integration.handler;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
@@ -158,8 +159,9 @@ public class DelayHandler extends AbstractReplyProducingMessageHandler implement
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the {@link Expression} that should be checked for a delay period (in
|
||||
* milliseconds) or a Date to delay until. If this property is set, the result of the
|
||||
* Specify the {@link Expression} that should be checked for a delay period
|
||||
* (in milliseconds) or a {@link Date}, or {@link Instant} to delay until.
|
||||
* If this property is set, the result of the
|
||||
* expression evaluation (if not null) will take precedence over this handler's
|
||||
* default delay.
|
||||
* @param delayExpression The delay expression.
|
||||
@@ -169,8 +171,9 @@ public class DelayHandler extends AbstractReplyProducingMessageHandler implement
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the {@code Expression} that should be checked for a delay period (in
|
||||
* milliseconds) or a Date to delay until. If this property is set, the result of the
|
||||
* Specify the {@code Expression} that should be checked for a delay period
|
||||
* (in milliseconds) or a {@link Date}, or {@link Instant} to delay until.
|
||||
* If this property is set, the result of the
|
||||
* expression evaluation (if not null) will take precedence over this handler's
|
||||
* default delay.
|
||||
* @param delayExpression The delay expression.
|
||||
@@ -364,6 +367,12 @@ public class DelayHandler extends AbstractReplyProducingMessageHandler implement
|
||||
: System.currentTimeMillis();
|
||||
delay = ((Date) delayValue).getTime() - current;
|
||||
}
|
||||
else if (delayValue instanceof Instant) {
|
||||
long current = delayedMessageWrapper != null
|
||||
? delayedMessageWrapper.getRequestDate()
|
||||
: Instant.now().toEpochMilli();
|
||||
delay = ((Instant) delayValue).minusMillis(current).toEpochMilli();
|
||||
}
|
||||
else if (delayValue != null) {
|
||||
try {
|
||||
delay = Long.valueOf(delayValue.toString());
|
||||
@@ -391,8 +400,7 @@ public class DelayHandler extends AbstractReplyProducingMessageHandler implement
|
||||
|
||||
private void releaseMessageAfterDelay(final Message<?> message, long delay) {
|
||||
Message<?> delayedMessage = message;
|
||||
|
||||
DelayedMessageWrapper messageWrapper = null;
|
||||
DelayedMessageWrapper messageWrapper;
|
||||
if (message.getPayload() instanceof DelayedMessageWrapper) {
|
||||
messageWrapper = (DelayedMessageWrapper) message.getPayload();
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.springframework.integration.StaticMessageHeaderAccessor;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.channel.MessagePublishingErrorHandler;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.config.IntegrationEvaluationContextFactoryBean;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.store.MessageGroup;
|
||||
import org.springframework.integration.store.MessageGroupStore;
|
||||
@@ -93,13 +94,16 @@ public class DelayHandlerTests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.context.registerBean(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME,
|
||||
new IntegrationEvaluationContextFactoryBean());
|
||||
this.context.refresh();
|
||||
input.setBeanName("input");
|
||||
output.setBeanName("output");
|
||||
taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.afterPropertiesSet();
|
||||
delayHandler = new DelayHandler(DELAYER_MESSAGE_GROUP_ID, taskScheduler);
|
||||
delayHandler.setOutputChannel(output);
|
||||
delayHandler.setBeanFactory(mock(BeanFactory.class));
|
||||
delayHandler.setBeanFactory(this.context);
|
||||
input.subscribe(delayHandler);
|
||||
output.subscribe(resultHandler);
|
||||
}
|
||||
@@ -232,6 +236,18 @@ public class DelayHandlerTests {
|
||||
assertNotSame(Thread.currentThread(), resultHandler.lastThread);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delayHeaderIsInstantInTheFutureAndDefaultDelayWouldTimeout() {
|
||||
this.delayHandler.setDefaultDelay(5000);
|
||||
this.delayHandler.setDelayExpressionString("T(Instant).now().plusMillis(150)");
|
||||
startDelayerHandler();
|
||||
Message<?> message = new GenericMessage<>("test");
|
||||
this.input.send(message);
|
||||
waitForLatch(10000);
|
||||
assertSame(message.getPayload(), this.resultHandler.lastMessage.getPayload());
|
||||
assertNotSame(Thread.currentThread(), this.resultHandler.lastThread);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delayHeaderIsDateInThePastAndDefaultDelayWouldTimeout() {
|
||||
delayHandler.setDefaultDelay(5000);
|
||||
|
||||
Reference in New Issue
Block a user