The reference manul talked about how to set this in XML, and I saw the Jira issue for advanced configuration for #Aggregator completed but not seeing those advanced properties. So if using annotation, how to set expire group?
Well, according that JIRA ticket there is indeed a sample in the Reference Manual:
#ServiceActivator(inputChannel = "aggregatorChannel")
#Bean
public MessageHandler aggregator(MessageGroupStore jdbcMessageGroupStore) {
AggregatingMessageHandler aggregator =
new AggregatingMessageHandler(new DefaultAggregatingMessageGroupProcessor(),
jdbcMessageGroupStore);
aggregator.setOutputChannel(resultsChannel());
aggregator.setGroupTimeoutExpression(new ValueExpression<>(500L));
aggregator.setTaskScheduler(this.taskScheduler);
return aggregator;
}
And there is an explicit note on the matter:
Annotation configuration (#Aggregator and others) for the Aggregator component covers only simple use cases, where most default options are sufficient. If you need more control over those options using Annotation configuration, consider using a #Bean definition for the AggregatingMessageHandler and mark its #Bean method with #ServiceActivator
Even would be better to use this:
Starting with the version 4.2 the AggregatorFactoryBean is available, to simplify Java configuration for the AggregatingMessageHandler.
Seems for me everything is covered in the Docs. Is anything missed?
I mean the AggregatorFactoryBean has an option you need:
public void setExpireGroupsUponCompletion(Boolean expireGroupsUponCompletion) {
Is that not enough?
Related
Do I really need to define 2 advices over ServiceActivator (RequestHandlerRetryAdvice) if I need to use RetryTemplate (with AlwaysRetryPolicy) and ExpressionEvaluatingRequestHandlerAdvice where I filter the error that I don't want to retry on?
#Bean
#ServiceActivator(inputChannel = "outboundChannel", adviceChain = {"retry", "filter"})
public MessageHandler handler() {
JdbcMessageHandler ...
}
This works fine, but why can't I do it within one place only?
Or I should override canRetry method of AlwaysRetryPolicy and do this form there?
I tired that (retuned false) but it caused some circular loop.
I think I said you before over here: RetryTemplate with ServiceActivator and JdbcMessageHandler
See different RetryPolicy strategy implementations
I think a BinaryExceptionClassifierRetryPolicy should meet your requirements:
* A policy, that is based on {#link BinaryExceptionClassifier}. Usually, binary
* classification is enough for retry purposes. If you need more flexible classification,
* use {#link ExceptionClassifierRetryPolicy}.
You also can implement a custom RetryPolicy which would delegate to something like BinaryExceptionClassifierRetryPolicy but then do some some other logic according to the SQLException and its error code.
The RequestHandlerRetryAdvice.recoveryCallback may be used to deal with exceptions which were retries or not.
I'm using spring-boot-starter-data-cassandra-reactive(version 3.2.4) and have provided all the spring.data.cassaandra properties is application.yml. It works fine. But I need to add some customCassandraConversion so I extended AbstractCassandraConfiguration. The moment I extend AbstractCassandraConfiguration the application.yml aka the CassandraAutoConfiguration stops working. Is there another way to to configure customConversions without overriding AbstractCassandraConfiguration. Or how can I get both working? I'm using spring-boot 2.5.4
You can register your custom conversions as a Bean in config and they'll be picked up by AbstractCassandraConfiguration.
#Bean
public CassandraCustomConversions customConversions() {
// Add your converters here
List<?> converters = Arrays.asList(...)
return new CassandraCustomConversions(convert));
}
1) I would like to create a bean of HttpRequestExecutingMessageHandler (outbound channel adapter for HTTP) and specify the channel via an annotation like #OutboundChannelAdapter, why this is not possible? I suppose there is some design decision that I'm not understanding.
2) What is the suggested way of define HttpRequestExecutingMessageHandler without using XML configuration files? Do I have to configure the bean and set it manually?
Thanks in advance.
The #ServiceActivator fully covers that functionality. Unlike #Transformer it doesn't require a return value. So, your POJO method can be just void and the flow is going to stop there similar way a <outbound-channel-adapter> does that in XML configuration.
But in case of HttpRequestExecutingMessageHandler we need to worry about some extra option to make it one-way and stop there without care about any HTTP reply.
So, for the HttpRequestExecutingMessageHandler you need to declare a bean like:
#Bean
#ServiceActivator(inputChannel = )
public HttpRequestExecutingMessageHandler httpRequestExecutingMessageHandler() {
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler();
handler.setExpectReply(false)
return handler;
}
I think we need to improve docs on the matter anyway, but you can take a look into Java DSL configuration instead: https://docs.spring.io/spring-integration/docs/current/reference/html/#http-java-config. There is an Http.outboundChannelAdapter() for convenience.
I have been working on a "paved road" for setting up asynchronous messaging between two micro services using AMQP. We want to promote the use of separate domain objects for each service, which means that each service must define their own copy of any objects passed across the queue.
We are using Jackson2JsonMessageConverter on both the producer and the consumer side and we are using the Java DSL to wire the flows to/from the queues.
I am sure there is a way to do this, but it is escaping me: I want the consumer side to ignore the __TypeID__ header that is passed from the producer, as the consumer may have a different representation of that event (and it will likely be in in a different java package).
It appears there was work done such that if using the annotation #RabbitListener, an inferredArgumentTypeargument is derived and will override the header information. This is exactly what I would like to do, but I would like to use the Java DSL to do it. I have not yet found a clean way in which to do this and maybe I am just missing something obvious. It seems it would be fairly straight forward to derive the type when using the following DSL:
return IntegrationFlows
.from(
Amqp.inboundAdapter(factory, queueRemoteTaskStatus())
.concurrentConsumers(10)
.errorHandler(errorHandler)
.messageConverter(messageConverter)
)
.channel(channelRemoteTaskStatusIn())
.handle(listener, "handleRemoteTaskStatus")
.get();
However, this results in a ClassNotFound exception. The only way I have found to get around this, so far, is to set a custom message converter, which requires explicit definition of the type.
public class ForcedTypeJsonMessageConverter extends Jackson2JsonMessageConverter {
ForcedTypeJsonMessageConverter(final Class<?> forcedType) {
setClassMapper(new ClassMapper() {
#Override
public void fromClass(Class<?> clazz, MessageProperties properties) {
//this class is only used for inbound marshalling.
}
#Override
public Class<?> toClass(MessageProperties properties) {
return forcedType;
}
});
}
}
I would really like this to be derived, so the developer does not have to really deal with this.
Is there an easier way to do this?
The simplest way is to configure the Jackson converter's DefaultJackson2JavaTypeMapper with TypeIdMapping (setIdClassMapping()).
On the sending system, map foo:com.one.Foo and on the receiving system map foo:com.two.Foo.
Then, the __TypeId__ header gets foo and the receiving system will map it to its representation of a Foo.
EDIT
Another option would be to add an afterReceiveMessagePostProcessor to the inbound channel adapter's listener container - it could change the __TypeId__ header.
I am working on my first spring-integration use case. I would like to do everything in pure Spring Java Config (no XML configuration and DSL, only annotations). So far everything was OK despite lack of documentation and examples.
But now I have problem with delayer. There is no obvious annotation and there is nothing in documentation regarding configuring delayer in DSL or annotation. Is delayer supported only in XML configuration?
The Java DSL on the matter should be obvious:
#Bean
public IntegrationFlow delayFlow() {
return IntegrationFlows.from("delayInput")
.delay("delayer", d -> d
.delayExpression("200")
.advice(this.delayedAdvice)
.messageStore(messageStore()))
.get();
}
For the raw Java & Annotation configuration pay attention to Programming Tips and Tricks.
The main point for you is this:
If you are familiar with Spring Integration XML configuration already, starting with version 4.3, we provide in the XSD elements definitions the description with the pointer which target classes are used to produce beans for the adapter or gateway.
So, going to the <delayer> XSD we see:
<xsd:documentation>
Defines a Consumer Endpoint for the 'org.springframework.integration.handler.DelayHandler'
that passes a Message to the output-channel after a delay.
Having a sample above about sendChatMessageHandler() #Bean we can do the same for the DelayHandler:
#Bean
#ServiceActivator(inputChannel = "delayInput")
public MessageHandler delayMessageHandler() {
DelayHandler delayHandler = new DelayHandler("myGroup");
...
return delayHandler;
}
NOTE: The latest documentation for version 5.0 will contain a sample how to configure delayer via Annotations and Java DSL.