Мы рады сообщить вам о выпуске второго промежуточного расширения Java DSL для Spring Integration!
Артефакт org.springframework.integration:spring-integration-java-dsl:1.0.0.M2
доступен в Spring IO Milestone Repository.
2 промежуточный релиз включает несколько исправлений ошибок, нововведений и улучшений.
Спасибо всем тем, кто участвовал в первом релизе, оставлял отзывы, находил проблемы и делился мыслями.
Вот краткое описание того, что изменилось по сравнению с первым промежуточным релизом:
Обработчик лямбда
Как вы могли заметить, использование лямбда в Java 8 — это мощный инструмент для создания удобного и понятного DSL. Одна из просьб сообщества, которую мы получили, была возможность описания лямбда-выражений через .handle()
EIP-метод вместо того, чтобы описывать POJO и использовать их как метод объявления. Но было важно не потерять возможность «конвертации типов во время выполнения». Кроме того, вы не могли получать generic-тип для лямбд. После некоторого исследования, мы нашли решение с добавлением type
аргумента. Следовательно, было добавлено несколько новых методов к IntegrationFlowBuilder
:
<P> IntegrationFlowBuilder handle(GenericHandler<P> handler)
<P> IntegrationFlowBuilder handle(GenericHandler<P> handler,
EndpointConfigurer<GenericEndpointSpec<ServiceActivatingHandler>> endpointConfigurer)
<P> IntegrationFlowBuilder handle(Class<P> payloadType, GenericHandler<P> handler)
<P> IntegrationFlowBuilder handle(Class<P> payloadType, GenericHandler<P> handler,
EndpointConfigurer<GenericEndpointSpec<ServiceActivatingHandler>> endpointConfigurer)
Если вы будете использовать метод с указанием payloadType
аргумента и в handler
лямбду, последний аргумент будет являться оболочкой LambdaMessageProcessor
с ConversionService
. А сообщение payload
будет конвертировано в соответствующий type
. Тем самым, мы получили более лучшую слабую связность. Ниже простой пример, демонстрирующий это:
@Bean
public IntegrationFlow integerFlow() {
return IntegrationFlows.from("input")
.<byte[], String>transform(p -> new String(p, "UTF-8"))
.handle(Integer.class, (p, h) -> p * 2)
.get();
}
ConversionService
предотвращает появление ошибки ClassCastException: String cannot be cast to Integer
.
Тот же дополнительный аргумент был добавлен и в другие EIP-методы с лямбдами: .transform()
, .filter()
, .split()
и т.д.
Transformers Factory
Удобная, гибкая Transformers
фабрика была добавлена, чтобы использовать как внутренний объект с .transform()
EIP-методом:
@Bean
public IntegrationFlow transformFlow() {
return IntegrationFlows.from("input")
.transform(Transformers.xpath("/root/myJson", XPathEvaluationType.STRING_RESULT))
.transform(Transformers.fromJson(MyPojo.class))
.transform(Transformers.serializer())
.get();
}
Это позволяет избежать неудобное написание кода с использованием сеттеров, а также сделать поток определения более простым. Отмечу, что Transformers
может быть использован для определения целевых Transformer
‘ов как @Bean
‘ы и снова их использовать в определении IntegrationFlow
. Тем не менее, DSL парсер управляет определением бинов для внутренних объектов, если они ещё не определены как бины.
.gateway() EIP-метод
Т.к. определение IntegrationFlow
выглядит так же как и <chain>
из Spring Integration XML, мы ввели .gateway()
EIP-метод, который играет ту же роль, что и <gateway>
внутри <chain>
— отправляет сообщение requestChannel
какому-нибудь другому потоку сообщений и ждет результата из replyChannel
или из TemporaryReplyChannel
по умолчанию:
@Bean
@DependsOn("gatewayRequestFlow")
public IntegrationFlow gatewayFlow() {
return IntegrationFlows.from("gatewayInput")
.gateway("gatewayRequest", g -> g.errorChannel("gatewayError").replyTimeout(10L))
.get();
}
@Bean
public IntegrationFlow gatewayRequestFlow() {
return IntegrationFlows.from("gatewayRequest")
.filter("foo"::equals, f -> f.throwExceptionOnRejection(true))
.<String, String>transform(String::toUpperCase)
.get();
}
Адаптеры для протоколов
Конечно, основное назначение Spring Integration в обеспечении взаимодействия с другими внешними системами, где Protocol Adapters обеспечивают эту функциональность. С Spring Integration Java DSL вы можете использовать generic’и в определении бинов(@Bean
) для любых адаптеров конечной системы(например, MarshallingWebServiceInboundGateway
), но целью DSL является в обеспечении высокоуровнего API описания компонентов также, как это делают Spring Integration XML конфигурации.
Теперь, когда вы познакомились с возможностями наших Builder
и Lambda
, создадим что-нибудь на их основе. Классы были введены с набором статических методов делегировать IntegrationComponentSpec<S, P>
реализацию. Классы могут быть рассмотрены как «Namespace Factories», потому что они играют ту же роль, что и XML namespace для компонентов из конкретного модуля Spring Integration для конкретного протокола. На текущий момент, Spring Integration Java DSL поддерживает только пространства имен для фабрик Amqp
и Jms
:
@Bean
public IntegrationFlow amqpFlow() {
return IntegrationFlows.from(Amqp.inboundGateway(this.rabbitConnectionFactory, queue()))
.transform("hello "::concat)
.transform(String.class, String::toUpperCase)
.get();
}
@Bean
public IntegrationFlow amqpOutboundFlow() {
return IntegrationFlows.from("amqpOutboundInput")
.handle(Amqp.outboundAdapter(this.amqpTemplate).routingKeyExpression("headers.routingKey"))
.get();
}
@Bean
public IntegrationFlow jmsInboundFlow() {
return IntegrationFlows
.from(Jms.inboundAdapter(this.jmsConnectionFactory)
.configureJmsTemplate(t ->
t.deliveryPersistent(true)
.jmsMessageConverter(myMessageConverter()))
.destination("jmsInbound"))
.<String, String>transform(String::toUpperCase)
.channel(this.jmsOutboundInboundReplyChannel())
.get();
}
@Bean
public IntegrationFlow jmsOutboundGatewayFlow() {
return IntegrationFlows.from("jmsOutboundGatewayChannel")
.handle(Jms.outboundGateway(this.jmsConnectionFactory)
.replyContainer(c ->
c.concurrentConsumers(3)
.sessionTransacted(true))
.requestDestination("jmsPipelineTest"))
.get();
}
Мы показали здесь использование пространства имен фабрик как объявления внутренних адаптеров, кроме того, они могут быть использованы из определений @Bean
, делая цепочку IntegrationFlow
методов более понятной.
Мы спросили мнение сообщества по поводу этих пространств имен фабрик прежде, чем потратить усилия на другое; мы также попытались оценить приоритеты для реализации поддержки адаптеров/шлюзов.
Убедитесь в наличии конкретной spring-integration-[PROTOCOL].jar
зависимости в classpath, т.к. spring-integration-java-dsl
объявляет их как optional
, чтобы избежать накладных расходов на стороне конечного приложения.
Изменения DSL Parser
Тем не менее, основной целью этой версии М2 является критически важный вопрос о неправильном расположении DSL parser. Теперь он перемещен из IntegrationConfigurationBeanFactoryPostProcessor
в IntegrationFlowBeanPostProcessor
и Spring Integration Java DSL больше не влияет на контекст приложения — он просто следует определению жизненного цикла стандартного Spring бина. Возможно, вам придется внести некоторые изменения в существующие DSL приложения для этой версии.
В большинстве случаев ограничиваются channel auto-declaration
, когда мы не определяем явно определение MessageChannel
бина, но обращаемся к нему из компонентов интеграции. Если вы заметили, в .gateway()
из примера выше мы использовали @DependsOn
аннотацию. Это потому, что бины зарегистрированы и инициализированы по одному по порядку, как они определены в @Configuration
классах. Поскольку мы не используем определения бинов для MessageChannel
‘ов, контекст приложения не объявляет dependsOn
для бина, который использует этот канал, а с другой стороны, мы не объявляем MessageChannel
для всех, у нас есть только один выбор, который зависит от IntegrationFlow
.
Таким образом, вы объявляете явно MessageChannel
бины или используете @DependsOn
с соответствующим объявлением IntegrationFlow
бина для объявления последующих IntegrationFlow
каналов.
Выводы
Для получения подробной информации обратитесь к справочному руководству. Также, посмотрите Запись вебинара: Spring Integration 4.0 — новая граница, где Spring Integration Java DSL представлена в режиме «live coding».
И как обычно: пожалуйста, делитесь своими мыслями и мнениями: StackOverflow(spring-integration
), Spring JIRA.