Showing posts with label integration. Show all posts
Showing posts with label integration. Show all posts

Monday, 21 June 2021

Spring integration: why there is no outbound channel adapter

An outbound channel adapter endpoint connects a MessageChannel to a target system.

 


 

Outbound channel adapter is used to send the messages from internal messaging system to external service. @ServiceActivator annotation is capable of achieving this functionality.

 

Example

@ServiceActivator(inputChannel = "notifySecretMsg")
public void notifyExternalService(String msg) {
	System.out.println("Acknowledgement received for the message '" + msg + "'");
}


How can I configure Http requests to not worry about response from external service.

Set expect reply property to false, while delivering the message to external service.

@Bean
@ServiceActivator(inputChannel = "notifySecretMsg")
public HttpRequestExecutingMessageHandler httpRequestExecutingMessageHandler() {
	HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler();
	handler.setExpectReply(false)
    return handler;
}


Find the below working application.

 

Step 1: Create new maven project ‘outbound-adapter-demo’.

 

Step 2: Update pom.xml with maven dependencies.

 

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.sample.app</groupId>
	<artifactId>outbound-adapter-demo</artifactId>
	<version>1</version>

	<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent -->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.0</version>
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-integration</artifactId>
		</dependency>

	</dependencies>

</project>


Step 3: Define service activators.

 

PrintService.java

package com.sample.app.service;

import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

@Component
public class PrintService {

	@ServiceActivator(inputChannel = "secretMsgChannel", outputChannel = "notifySecretMsg")
	public String consumeStringMessage(Message<String> message) throws InterruptedException {
		System.out.println("Received message from secretMsgChannel : " + message.getPayload());

		return message.getPayload();
	}

	@ServiceActivator(inputChannel = "notifySecretMsg")
	public void notifyExternalService(String msg) {
		System.out.println("Acknowledgement received for the message '" + msg + "'");
	}
}


Step 4: Define main application.

 

App.java

package com.sample.app;

import java.util.UUID;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.InboundChannelAdapter;
import org.springframework.integration.annotation.Poller;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;

@SpringBootApplication
@Configuration
public class App {

	@InboundChannelAdapter(channel = "secretMsgChannel", poller = {
			@Poller(maxMessagesPerPoll = "2", fixedRate = "5000") })
	Message<String> getSecretMessageFromExternalSystem() {
		UUID uuid = UUID.randomUUID();
		String secretMsg = uuid.toString();

		return MessageBuilder.withPayload(secretMsg).build();

	}

	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}

}


Total project structure looks like below.




Run App.java, you will see below kind of messages in console.

Received message from secretMsgChannel : f319748c-dc72-4c80-8e50-0af114766cab
Acknowledgement received for the message 'f319748c-dc72-4c80-8e50-0af114766cab'
Received message from secretMsgChannel : fbc7851a-21d4-4922-94ec-ae5d02b418b7
Acknowledgement received for the message 'fbc7851a-21d4-4922-94ec-ae5d02b418b7'

 

You can download complete working application from below link.

https://github.com/harikrishna553/springboot/tree/master/spring-integration/outbound-adapter-demo

 


Previous                                                    Next                                                    Home

Spring integration: Channel adapters

Channel adapter endpoint is used to connect a message channel to some external system.

 

There are two types of channel adapters.

 

Inbound channel adapter

An inbound channel adapter endpoint connects a source system to a MessageChannel.


 



Outbound channel adapter

An outbound channel adapter endpoint connects a MessageChannel to a target system.

 


For example, you read a message from external system using Inbound channel adapter, apply filtering, transformation and other operations on the message and send it to other external system using outbound channel adapter.


 

 

Previous                                                    Next                                                    Home

Spring integration: Asynchronous gateways

By returning a Future or ListenableFuture from gateway method, we can make the gateway method asynchronous.

 

Step 1: Define gateway with ListenableFuture as return type.

@MessagingGateway
public interface CustomGateway {

	@Gateway(requestChannel = "printChannel")
	public ListenableFuture<String> sendToPrintChannel(String message);

}

 

Step 2: Use callback method to capture the asynchronous response.

ListenableFuture<String> reply = customGateway.sendToPrintChannel("Msg " + i);

reply.addCallback(new ListenableFutureCallback<String>() {

	@Override
	public void onSuccess(String result) {
		System.out.println(result);
	}

	@Override
	public void onFailure(Throwable ex) {
		ex.printStackTrace();
	}
});

 

Find the below working application.

 

Step 1: Create new maven project ‘asynchronous-gateway-demo’.

 

Step 2: Update pom.xml with maven dependencies.

 

pom.xml

 

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.sample.app</groupId>
	<artifactId>asynchronous-gateway-demo</artifactId>
	<version>1</version>

	<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent -->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.0</version>
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-integration</artifactId>
		</dependency>

	</dependencies>

</project>

Step 3: Define service activator.

 

PrintService.java

package com.sample.app.service;

import java.util.Random;
import java.util.concurrent.TimeUnit;

import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

@Component
public class PrintService {

	@ServiceActivator(inputChannel = "printChannel")
	public String consumeStringMessage(Message<String> message) throws InterruptedException {
		
		Random random = new Random();
		int timeToSleep = random.nextInt(10);
		
		TimeUnit.SECONDS.sleep(timeToSleep);
		
		System.out.println("Received message from printChannel : " + message.getPayload());		
		return "Message " + message.getPayload() + " received";
	}
	

}


Step 4: Define gateway.

 

CustomGateway.java

package com.sample.app.gateway;

import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.util.concurrent.ListenableFuture;

@MessagingGateway
public interface CustomGateway {

	@Gateway(requestChannel = "printChannel")
	public ListenableFuture<String> sendToPrintChannel(String message);

}

 

Step 5: Define main application class.

 

App.java

 

package com.sample.app;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;

import com.sample.app.gateway.CustomGateway;

@SpringBootApplication
@Configuration
public class App {

	@Autowired
	private CustomGateway customGateway;

	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}

	@Bean
	public CommandLineRunner demo() {
		return (args) -> {

			for (int i = 0; i < 5; i++) {
				ListenableFuture<String> reply = customGateway.sendToPrintChannel("Msg " + i);

				reply.addCallback(new ListenableFutureCallback<String>() {

					@Override
					public void onSuccess(String result) {
						System.out.println(result);
					}

					@Override
					public void onFailure(Throwable ex) {
						ex.printStackTrace();
					}
				});
			}

		};

	};

}

 

Total project structure looks like below.

 

 


Run App.java, you will see below kind of messages in console.

 

Received message from printChannel : Msg 1
Message Msg 1 received
Received message from printChannel : Msg 4
Message Msg 4 received
Received message from printChannel : Msg 0
Message Msg 0 received
Received message from printChannel : Msg 2
Message Msg 2 received
Received message from printChannel : Msg 3
Message Msg 3 received

 

You can download complete working application from below link.

https://github.com/harikrishna553/springboot/tree/master/spring-integration/asynchronous-gateway-demo

 

 

 

 

Previous                                                    Next                                                    Home

Saturday, 19 June 2021

Spring integration: GatewayHeader: Add headers at Gateway

You can add headers to a message using gateway.

 

How to add headers using @MessagingGateway annotation

‘defaultHeaders’ attribute is used to custom message headers. These default headers are created for all methods on the service-interface.

 

Example

@MessagingGateway(defaultHeaders = {@GatewayHeader(name = "root-header", value = "root123")})
public interface CustomGateway {

}

How to add headers using @Gateway annotation?

'headers' attribute is used specify additional headers that will be added to the request message.


@Gateway(requestChannel = "printChannel", headers = {
		@GatewayHeader(name = "secret", value = "my-secret123"),
		@GatewayHeader(name = "service-name", value = "my-service") })
public String sendToPrintChannel(String message);

 

Find the below working application.

 

Step 1: Create new maven project ‘gateway-headers-demo’.

 

Step 2: Update pom.xml with maven dependencies.

 

pom.xml

 

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.sample.app</groupId>
	<artifactId>gateway-headers-demo</artifactId>
	<version>1</version>

	<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent -->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.0</version>
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-integration</artifactId>
		</dependency>

	</dependencies>

</project>

Step 3: Define gateway.

 

CustomGateway.java

package com.sample.app.gateway;

import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.annotation.*;

@MessagingGateway(defaultHeaders = {@GatewayHeader(name = "root-header", value = "root123")})
public interface CustomGateway {

	@Gateway(requestChannel = "printChannel", headers = {
			@GatewayHeader(name = "secret", value = "my-secret123"),
			@GatewayHeader(name = "service-name", value = "my-service") })
	public String sendToPrintChannel(String message);

}


Step 4: Define service activator.

 

PrintService.java

package com.sample.app.service;

import java.util.Map;
import java.util.Set;

import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

@Component
public class PrintService {

	@ServiceActivator(inputChannel = "printChannel")
	public String consumeStringMessage(Message<String> message) {
		System.out.println("Received message from printChannel : " + message.getPayload());
		
		Set<Map.Entry<String, Object>> messageHeaders = message.getHeaders().entrySet();
		
		System.out.println("Headers are.....");
		for(Map.Entry<String, Object> entry: messageHeaders) {
			System.out.println(entry.getKey() + " -> " + entry.getValue());
		}
		
		return "Success";
	}
	

}


Step 5: Define main application class.

 

App.java

package com.sample.app;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.sample.app.gateway.CustomGateway;

@SpringBootApplication
@Configuration
public class App {

	@Autowired
	private CustomGateway customGateway;

	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}

	@Bean
	public CommandLineRunner demo() {
		return (args) -> {

			String reply = customGateway.sendToPrintChannel("Hello World");
			
			System.out.println("reply : " + reply);
		};

	};

}


Total project structure looks like below.




Run App.java, you will see below messages in console.

Received message from printChannel : Hello World
Headers are.....
service-name -> my-service
replyChannel -> org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@64712be
errorChannel -> org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@64712be
root-header -> root123
secret -> my-secret123
id -> f3f45661-6f2e-b0c4-5503-04c302aeb937
timestamp -> 1617701164345
reply : Success


You can download complete working application from below link.

https://github.com/harikrishna553/springboot/tree/master/spring-integration/gateway-headers-demo



 

Previous                                                    Next                                                    Home