Spring Integration Java DSL 里程碑 2 已發布

發布 | Artem Bilan | 2014 年 6 月 18 日 | ...

我們很高興宣布發布 Spring Integration 的 Java DSL 擴充功能的第二個里程碑!

org.springframework.integration:spring-integration-java-dsl:1.0.0.M2 artifact 可從 Spring IO 里程碑儲存庫 取得。

里程碑 2 包含數個錯誤修正、一些新功能和進一步的改進。

感謝所有嘗試過里程碑 1、提供意見反應、提出問題並分享想法的人。

以下是自 里程碑 1 以來的主要變更摘要

Lambda 處理器

您可能已經注意到,使用 Java 8 Lambdas 是使此 DSL 方便且易於閱讀的強大工具。 我們收到的一個社群請求是允許為 .handle() EIP 方法宣告 Lambda,而不是必須宣告 POJO 並將其用作方法調用。 但一個顧慮是不要失去「運行時類型轉換」。 但是,您無法取得 Lambdas 的泛型類型。 經過一番調查,我們透過新增 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 是 Lambda 的方法變體,則最後一個參數將是 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

相同的附加類型引數已新增至其他帶有 Lambdas 的 EIP 方法:.transform().filter().split() 等。

轉換器工廠

已新增方便、流暢的 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();
}

它可以避免使用 setter 進行不方便的編碼,並使流程定義更加直接。 請注意,Transformers 可用於將目標 Transformer 宣告為 @Bean,並再次從 IntegrationFlow 定義中使用它們。 儘管如此,如果尚未將 DSL 解析器定義為 bean,則它會處理內聯物件的 bean 宣告。

.gateway() EIP 方法

由於 IntegrationFlow 定義看起來類似於 Spring Integration XML 中的 <chain>,因此我們引入了 .gateway() EIP 方法,該方法的作用與 <chain> 中的 <gateway> 相同 - 將訊息傳送到某些其他訊息流程的 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 的大部分價值是由於與某些外部系統的互動提供的,其中通訊協定介面卡提供了該功能。 借助 Spring Integration Java DSL,我們可以繼續將泛型 bean 定義 (@Bean) 用於任何終端系統介面卡(例如 MarshallingWebServiceInboundGateway),但 DSL 的目的是提供更高等級的 API,以類似於 Spring Integration XML 設定提供的方式宣告元件。

由於您現在熟悉我們的 BuilderLambda 功能,因此我們以這些技術為基礎。 已引入帶有一組靜態方法的類別,以委派給某些底層 IntegrationComponentSpec<S, P> 實作。 這些類別可以被視為「命名空間工廠」,因為它們在具體通訊協定特定的 Spring Integration 模組中扮演與 XML 命名空間相同的角色。 目前,Spring Integration Java DSL 僅支援 AmqpJms 命名空間工廠

@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 及其所需的依賴項,因為 spring-integration-java-dsl 將它們宣告為 optional 以避免不必要的終端應用程式開銷。

DSL 解析器變更

儘管如此,此 M2 版本的總體目的是解決 DSL 解析器的錯誤位置這一關鍵問題。 現在它已從 IntegrationConfigurationBeanFactoryPostProcessor 移至 IntegrationFlowBeanPostProcessor,並且 Spring Integration Java DSL 不再影響應用程式內容 - 它只是遵循標準的 Spring bean 定義生命週期。 您可能需要對現有的 DSL 應用程式進行一些變更才能使用此版本。

在大多數情況下,這僅限於 channel auto-declaration,當我們不定義顯式的 MessageChannel bean 定義時,而是從整合元件引用它。 如果您在上面的 .gateway() 範例中注意到,我們使用了 @DependsOn 註釋。 這是因為 bean 會在 @Configuration 類別中宣告時一個一個地註冊和初始化。 由於我們不對 MessageChannel 使用 bean 定義,因此應用程式內容無法自動宣告 bean 的 dependsOn,該 bean 使用通道,並且從另一方面來說,我們根本不宣告 MessageChannel bean,我們只有一種選擇來依賴 IntegrationFlow bean。

因此,您可以選擇顯式宣告 MessageChannel bean,或者在下游 IntegrationFlow 的適當 IntegrationFlow bean 定義上使用 @DependsOn,該下游 IntegrationFlow 宣告隱式通道。

總結

請參閱上面提到的參考手冊以獲取更多資訊。 並查看[網路研討會重播:Spring Integration 4.0 - 新的邊界] (https://spring.dev.org.tw/blog/2014/05/15/webinar-replay-spring-integration-4-0-the-new-frontier),其中 Spring Integration Java DSL 已透過「現場編碼」引入。

與往常一樣:請隨時分享您的想法和回饋:StackOverflowspring-integration 標籤)、Spring JIRA

SpringOne 2GX 2014 即將到來

儘早預訂您在 德州達拉斯舉行的 SpringOne2GX 的位置(9 月 8 日至 11 日)。 這絕對是第一手了解所有資訊並提供直接回饋的最佳機會。 預計今年會有一些重要的新公告。 我們預計將會舉辦一些深入的 Spring-Integration 會議。

取得 Spring 電子報

隨時關注 Spring 電子報

訂閱

搶先一步

VMware 提供培訓和認證,以加速您的進展。

了解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位檔案。

了解更多

即將舉行的活動

查看 Spring 社群中所有即將舉行的活動。

查看全部