RabbitMq RepublishMessageRecover ignore ImmediateAcknowledgeAmqpException - java

Im creating a RabbitMQ consumer using...
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
My Listener looks like this...
#RabbitListener(queues = "queue")
public void getMessages(String message) {
if(message.contains("error")) {
throw new ImmediateAcknowledgeAmqpException("Invalid message, discarding");
}
throw new AmqpRejectAndDontRequeueException("Re-queuing message");
}
Im expecting ImmediateAcknowledgeAmqpException to discard the message totally but it keeps ending up on the deadletter queue :( Heres my configuration
#Bean
public RepublishMessageRecoverer republishMessageRecoverer(RabbitTemplate rabbitTemplate) {
RepublishMessageRecoverer republishMessageRecoverer = new RepublishMessageRecoverer(rabbitTemplate,"exchange", "deadletter_routing_key");
return republishMessageRecoverer;
}
Bean
public SimpleRetryPolicy simpleRetryPolicy() {
Map<Class<? extends Throwable>, Boolean> includeExceptions = new HashMap<>();
includeExceptions.put(ImmediateAcknowledgeAmqpException.class, false);
includeExceptions.put(AmqpRejectAndDontRequeueException.class, true);
return new SimpleRetryPolicy(5, includeExceptions, true);
}
#Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory,
SimpleRetryPolicy simpleRetryPolicy, RepublishMessageRecoverer republishMessageRecoverer) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setDefaultRequeueRejected(false);
factory.setAdviceChain(RetryInterceptorBuilder
.stateless()
.retryPolicy(simpleRetryPolicy)
.recoverer(republishMessageRecoverer)
.backOffOptions(5000, 1,
1000)
.build());
return factory;
}
Is there a way I can exclude the ImmediateAcknowledgeAmqpException from the recoverer?
Thanks

Related

How to publish Spring Kafka DLQ in 2.5.4 version

need your help and guidance on this.
I was using 2.2.X version spring-kafka in my current project.
The error handling that I created looks like this:
#Bean("kafkaConsumer")
public ConcurrentKafkaListenerContainerFactory<String, Map<String, Object>> eventKafkaConsumer() {
ConcurrentKafkaListenerContainerFactory<String, Map<String, Object>> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setErrorHandler(new SeekToCurrentErrorHandler(createDeadLetterPublishingRecoverer(), 3));
return factory;
}
public DeadLetterPublishingRecoverer createDeadLetterPublishingRecoverer() {
return new DeadLetterPublishingRecoverer(getEventKafkaTemplate(),
(record, ex) -> new TopicPartition("topic-undelivered", -1));
}
And then I upgraded all my project dependency version, such as spring-boot and the spring-kafka into the latest one : 2.5.4 RELEASE
I found that some of the methods were deprecated and changed.
SeekToCurrentErrorHandler
SeekToCurrentErrorHandler errorHandler =
new SeekToCurrentErrorHandler((record, exception) -> {
// recover after 3 failures, woth no back off - e.g. send to a dead-letter topic
}, new FixedBackOff(0L, 2L));
My question is,
how to produce the DLQ with these configurations:
EDITED
#Bean("kafkaConsumer")
public ConcurrentKafkaListenerContainerFactory<String, Map<String, Object>> kafkaConsumer() {
ConcurrentKafkaListenerContainerFactory<String, Map<String, Object>> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
factory.setConcurrency(consumerConcurrencyCount);
factory.setErrorHandler(errorHandler());
return factory;
}
public SeekToCurrentErrorHandler errorHandler() {
return new SeekToCurrentErrorHandler(
deadLetterPublishingRecoverer(),
new FixedBackOff(0L, 2L)
);
}
public DeadLetterPublishingRecoverer deadLetterPublishingRecoverer() {
return new DeadLetterPublishingRecoverer(
getEventKafkaTemplate(),
(record, ex) -> {
if (ex.getCause() instanceof BusinessException || ex.getCause() instanceof TechnicalException) {
return new TopicPartition("topic-undelivered", -1);
}
return new TopicPartition("topic-fail", -1);
});
}
public KafkaOperations<String, Object> getEventKafkaTemplate() { // producer to DLQ
return new KafkaTemplate<>(new DefaultKafkaProducerFactory<>(producerConfigs()));
}
This configurations work, thanks to Gary!
Thanks in advance
It's not clear what you mean by
The problem is, in the documentation, it's still using the old method, which is deprecated for 2.5.X version
The KafkaOperations is an interface that the KafkaTemplate implements; the only change you need to make is to change the maxAttempts to a BackOff...
#Bean("kafkaConsumer")
public ConcurrentKafkaListenerContainerFactory<String, Map<String, Object>> eventKafkaConsumer() {
ConcurrentKafkaListenerContainerFactory<String, Map<String, Object>> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setErrorHandler(new SeekToCurrentErrorHandler(createDeadLetterPublishingRecoverer(), new FixedBackOff(0, 2L));
return factory;
}
public DeadLetterPublishingRecoverer createDeadLetterPublishingRecoverer() {
return new DeadLetterPublishingRecoverer(getEventKafkaTemplate(),
(record, ex) -> new TopicPartition("topic-undelivered", -1));
}

Java Spring Reactive - RabbitMQ Listener ReplyTo/Exchange Exception

I've been trying to setup a reactive rabbitmq listener following the guidelines on https://www.baeldung.com/spring-amqp-reactive.
What I'm hoping for my code to do is
receive a message (works so far)
do a whole bunch of logic that ultimately returns a Flux response (ie. async calls to endpoints and dbs)
return the Flux as shown in the guide
When I attempt to run through the process with a sample event, I receive the following exception:
org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Listener threw exception
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.wrapToListenerExecutionFailedExceptionIfNeeded(AbstractMessageListenerContainer.java:1651)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1555)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1478)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1466)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1461)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1410)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:870)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:854)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:78)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1137)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1043)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.springframework.amqp.rabbit.listener.adapter.ReplyFailureException: Failed to send reply with payload 'InvocationResult [returnValue=FluxSwitchIfEmpty, returnType=null]'
at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.doHandleResult(AbstractAdaptableMessageListener.java:385)
at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.handleResult(AbstractAdaptableMessageListener.java:339)
at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.handleResult(AbstractAdaptableMessageListener.java:302)
at org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter.onMessage(MessageListenerAdapter.java:294)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1552)
... 12 common frames omitted
Caused by: org.springframework.amqp.AmqpException: Cannot determine ReplyTo message property value: Request message does not contain reply-to property, and no default response Exchange was set.
at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.getReplyToAddress(AbstractAdaptableMessageListener.java:465)
at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.doHandleResult(AbstractAdaptableMessageListener.java:381)
... 16 common frames omitted
From the message it looks like the problem stems from the published message not having a 'ReplyTo' property for specifying where the returned Flux should go to. This property is something that I will not be able to add. I've tried configuring a default exchange but nothing I've done seems to be working there. The code thats applicable is:
Configuration
#Bean
MessageConverter messageConverter() {
Jackson2JsonMessageConverter messageConverter = new Jackson2JsonMessageConverter() {
#Override
public Object fromMessage(Message message, Object conversionHint) throws MessageConversionException {
message.getMessageProperties().setContentType(MessageProperties.CONTENT_TYPE_JSON);
return super.fromMessage(message, conversionHint);
}
};
messageConverter.setClassMapper(classMapper());
return messageConverter;
}
#Bean
DefaultClassMapper classMapper() {
DefaultClassMapper classMapper = new DefaultClassMapper();
classMapper.setDefaultType(NotificationEvent.class);
return classMapper;
}
#Bean
MessageListenerAdapter listenerAdapter(ReactiveNotificationController notificationHandler) {
MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(notificationHandler, messageConverter());
messageListenerAdapter.setDefaultListenerMethod("receive");
return messageListenerAdapter;
}
#Bean
SimpleMessageListenerContainer container(ConnectionFactory rabbitListenerConnectionFactory,
MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(rabbitListenerConnectionFactory);
container.setQueues(queue());
container.setReceiveTimeout(2000);
container.setMessageListener(listenerAdapter);
container.setTaskExecutor(Executors.newCachedThreadPool());
container.setDefaultRequeueRejected(false);
return container;
}
#Bean
Queue queue() {
Map<String, Object> arguments = new HashMap<>();
arguments.put("x-dead-letter-exchange", deadLetterQueueBaseName);
arguments.put("x-dead-letter-routing-key", deadLetterQueueBaseName);
return new Queue(queueName, true, false, false, arguments);
}
#Bean
TopicExchange exchange() {
return new TopicExchange(queueName, true, false);
}
#Bean
Declarables declarables() {
return new Declarables(new ArrayList<>(bindings()));
}
#Bean
List<Binding> bindings() {
List<Binding> bindings = new ArrayList<>();
//Have the notification queue listen on both the deadLetterQueue routing key as well as the base one
bindings.add(BindingBuilder.bind(queue()).to(exchange()).with(deadLetterQueueBaseName));
bindings.add(BindingBuilder.bind(queue()).to(exchange()).with(""));
//bind parent exchanges to our child exchange
for (String parentExchangeName : parentExchangeNames) {
FanoutExchange thisExchange = new FanoutExchange(parentExchangeName);
bindings.add(BindingBuilder.bind(exchange()).to(thisExchange));
}
return bindings;
}
#Bean
public RabbitProperties rabbitProperties(AmqpAdmin rabbitAdmin, AmqpTemplate rabbitTemplate) {
return new RabbitProperties(rabbitAdmin, rabbitTemplate, deadLetterQueueBaseName, exchange(), baseTimeToLive);
}
Receiver Controller
#RestController
#Slf4j
public class ReactiveNotificationController {
private RabbitProperties rabbitProperties;
private EventSubscriptionService subscriptionService;
private NotificationSenderFactory senderFactory;
#Value("${kibo.rabbitmq.queueName}")
private String queueName;
public ReactiveNotificationController(RabbitProperties rabbitProperties,
EventSubscriptionService subscriptionService,
NotificationSenderFactory senderFactory) {
this.rabbitProperties = rabbitProperties;
this.subscriptionService = subscriptionService;
this.senderFactory = senderFactory;
}
#GetMapping(value = "/queue/{queueName}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
#SendTo("{queueName}")
public Flux<?> receive(NotificationEvent event) {
NotificationWorker worker = new NotificationWorker(event, rabbitProperties, subscriptionService, senderFactory);
return worker.run();
}
}
The error still exists if I force the receive method to just return a Flux.empty() value so I don't think the worker has anything to do with it. Any help on this would be greatly appreciated.

Spring boot JMS Listener - org.springframework.jms.config.JmsListenerEndpointRegistry.isAutoStartup()Z

I have setup a JmsListener to read messages from a sqs queue.
Firtsly i created a configuration class like below to setup a ConnectionFactory and JMSTemplate
#Configuration
#EnableJms
public class SQSJmsConfig {
private AWSCredentialsProvider awsCredentialsProvider;
#Value("${aws.ses.accessKey}")
private String accessKey;
#Value("${aws.ses.secretKey}")
private String secretKey;
#Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);
SQSConnectionFactory sqsConnectionFactory = new SQSConnectionFactory(new ProviderConfiguration(),
AmazonSQSClientBuilder.standard().withRegion(Regions.US_EAST_1).withCredentials(awsCredentialsProvider));
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(sqsConnectionFactory);
factory.setDestinationResolver(new DynamicDestinationResolver());
factory.setConcurrency("3-10");
factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
return factory;
}
#Bean
public JmsTemplate defaultJmsTemplate() {
AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);
SQSConnectionFactory sqsConnectionFactory = new SQSConnectionFactory(new ProviderConfiguration(),
AmazonSQSClientBuilder.standard().withRegion(Regions.US_EAST_1).withCredentials(awsCredentialsProvider));
return new JmsTemplate(sqsConnectionFactory);
}
}
Then i created a JmsListener method to read messages from sqs queue
#Service
public class SQSQueueService {
private static final Logger log = LoggerFactory.getLogger(SQSQueueService.class);
#JmsListener(destination = "${aws.sqs.queueName}")
public void readPlan(SQSEmailStatusQueue sqsEmailStatusQueue) {
try {
log.info("SNS notification received from SQS queue");
String message = sqsEmailStatusQueue.getMessage();
System.out.println(message);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
After that when i run the project i got the following exception
java.lang.AbstractMethodError: org.springframework.jms.config.JmsListenerEndpointRegistry.isAutoStartup()Z
What is the reason for this exception ?
The problem was with the dependency.
`<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>`
I removed the version from this. Then it worked.
Can anybody please explain me why it happened ?
The failure can occure if your application utilizes spring-boot-starter-parent and additionally depends on:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.jms.version}</version>
</dependency>
Utilize this dependency provided by the parent instead:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>

RabbitMQ fail connection

I need help, my app (client) connect to RabbitMQ server and when server shutdown, my app cannot start....
Listener can't created and app failed start.
Or when virtual host dont have queue my app cant start too
So my question
1) How to process exception in my config (all exception, i need was my app start if RabbitMQ server have problems)
2) What in my config look bad and need refactor
i use
Spring 4.2.9.RELEASE
org.springframework.amqp 2.0.5.RELEASE
Java 8
My 2 classes
1) Config for Beans RabbitMq
2) Listener annotation
#EnableRabbit
#Configuration
public class RabbitMQConfig {
#Bean
public ConnectionFactory connectionFactory() {
com.rabbitmq.client.ConnectionFactory factoryRabbit = new com.rabbitmq.client.ConnectionFactory();
factoryRabbit.setNetworkRecoveryInterval(10000);
factoryRabbit.setAutomaticRecoveryEnabled(true);
CachingConnectionFactory connectionFactory =
new CachingConnectionFactory(factoryRabbit);
connectionFactory.setHost("DRIVER_APP_IP");
connectionFactory.setPort(5672);
connectionFactory.setConnectionTimeout(5000);
connectionFactory.setRequestedHeartBeat(10);
connectionFactory.setUsername("user");
connectionFactory.setPassword("pass");
connectionFactory.setVirtualHost("/vhost");
return connectionFactory;
}
#Bean
public RabbitTemplate rabbitTemplate() {
try {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory());
rabbitTemplate.setRoutingKey(this.DRIVER_QUEUE);
rabbitTemplate.setQueue(this.DRIVER_QUEUE);
return rabbitTemplate;
} catch (Exception ex){
return new RabbitTemplate();
}
}
#Bean
public Queue queue() {
return new Queue(this.DRIVER_QUEUE);
}
#Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setConcurrentConsumers(3);
factory.setMaxConcurrentConsumers(10);
return factory;
}
}
#Component
public class RabbitMqListener {
#RabbitListener(bindings = #QueueBinding(
value = #Queue(value = DRIVER_QUEUE, durable = "true"),
exchange = #Exchange(value = "exchange", ignoreDeclarationExceptions = "true", autoDelete = "true"))
)
public String balancer(byte[] message) throws InterruptedException {
String json = null;
try {
"something move"
} catch (Exception ex) {
}
}
I found solution my problem
First it's Bean container!
We need this
factory.setMissingQueuesFatal(false);
this property give our when queue lost on server RabbitMQ, our app don't crash and can start
#Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setMissingQueuesFatal(false);
factory.setConcurrentConsumers(3);
factory.setStartConsumerMinInterval(3000L);
factory.setMaxConcurrentConsumers(10);
factory.setRecoveryInterval(15000L);
factory.setStartConsumerMinInterval(1000L);
factory.setReceiveTimeout(10000L);
factory.setChannelTransacted(true);
return factory;
}
and second
#Component
public class RabbitMqListener {
#RabbitListener(containerFactory = "rabbitListenerContainerFactory", queues = DRIVER_QUEUE)
public String balancer(byte[] message) throws InterruptedException {
String json = null;
try {
"something move"
} catch (Exception ex) {
}
}
I set containerFactory and Queue in #RabbitListener and drop other propertys,
because i don't need it
I hope it's help somebody, thank all for you attention and sorry for my English

Spring Integration using DSL for reading file from Unix location

I have a requirement where i need to look for a file continuously at unix location.Once its available then i need to parse it and convert to some json format.This needs to be done using Spring integration - DSL.
Following is the piece of code I got from spring site but it shows following exception:
o.s.integration.handler.LoggingHandler: org.springframework.messaging.MessageDeliveryException: Dispatcher has no subscribers for channel 'application.processFileChannel'.; nested exception is org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
Below is the code:
#SpringBootApplication
public class FileReadingJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(FileReadingJavaApplication.class)
.web(false)
.run(args);
}
#Bean
public IntegrationFlow fileReadingFlow() {
return IntegrationFlows
.from(s -> s.file(new File("Y://"))
.patternFilter("*.txt"),
e -> e.poller(Pollers.fixedDelay(1000)))
.transform(Transformers.fileToString())
.channel("processFileChannel")
.get();
}
}
New Code:
#SpringBootApplication
public class SpringIntegration {
public static void main(String[] args) {
new SpringApplicationBuilder(SpringIntegration.class)
.web(false)
.run(args);
}
#Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost("ip");
factory.setPort(port);
factory.setUser("username");
factory.setPassword("pwd");
factory.setAllowUnknownKeys(true);
return new CachingSessionFactory<LsEntry>(factory);
}
#Bean
public SftpInboundFileSynchronizer sftpInboundFileSynchronizer() {
SftpInboundFileSynchronizer fileSynchronizer = new SftpInboundFileSynchronizer(sftpSessionFactory());
fileSynchronizer.setDeleteRemoteFiles(false);
fileSynchronizer.setRemoteDirectory("remote dir");
fileSynchronizer.setFilter(new SftpSimplePatternFileListFilter("*.txt"));
return fileSynchronizer;
}
#Bean
#InboundChannelAdapter(channel = "sftpChannel", poller = #Poller(fixedDelay = "1000", maxMessagesPerPoll = "1"))
public MessageSource ftpMessageSource() {
SftpInboundFileSynchronizingMessageSource source =
new SftpInboundFileSynchronizingMessageSource(sftpInboundFileSynchronizer());
source.setLocalFilter(new AcceptOnceFileListFilter<File>());
source.setLocalDirectory(new File("Local directory"));
return source;
}
#Bean
#ServiceActivator(inputChannel = "fileInputChannel")
public MessageHandler handler() {
return new MessageHandler() {
#Override
public void handleMessage(Message<?> message) throws MessagingException {
System.out.println("File Name : "+message.getPayload());
}
};
}
#Bean
public static StandardIntegrationFlow processFileFlow() {
return IntegrationFlows
.from("fileInputChannel").split()
.handle("fileProcessor", "process").get();
}
#Bean
#InboundChannelAdapter(value = "fileInputChannel", poller = #Poller(fixedDelay = "1000"))
public MessageSource<File> fileReadingMessageSource() {
AcceptOnceFileListFilter<File> filters =new AcceptOnceFileListFilter<>();
FileReadingMessageSource source = new FileReadingMessageSource();
source.setAutoCreateDirectory(true);
source.setDirectory(new File("Local directory"));
source.setFilter(filters);
return source;
}
#Bean
public FileProcessor fileProcessor() {
return new FileProcessor();
}
#Bean
#ServiceActivator(inputChannel = "fileInputChannel")
public AmqpOutboundEndpoint amqpOutbound(AmqpTemplate amqpTemplate) {
AmqpOutboundEndpoint outbound = new AmqpOutboundEndpoint(amqpTemplate);
outbound.setExpectReply(true);
outbound.setRoutingKey("foo"); // default exchange - route to queue 'foo'
return outbound;
}
#MessagingGateway(defaultRequestChannel = "amqpOutboundChannel")
public interface MyGateway {
String sendToRabbit(String data);
}
}
FileProcessor:
public class FileProcessor {
public void process(Message<String> msg) {
String content = msg.getPayload();
JSONObject jsonObject ;
Map<String, String> dataMap = new HashMap<String, String>();
for(int i=0;i<=content.length();i++){
String userId = content.substring(i+5,i+16);
dataMap = new HashMap<String, String>();
dataMap.put("username", username.trim());
i+=290; //each record of size 290 in file
jsonObject = new JSONObject(dataMap);
System.out.println(jsonObject);
}
}
}
Your code is correct , but an exception tells you that there is need something what will read messages from the direct channel "processFileChannel".
Please, read more about different channel types in the Spring Integration Reference Manual.
EDIT
One of first class citizen in Spring Integration is MessageChannel abstraction. See EIP for more information.
The definition like .channel("processFileChannel") mean declare DirectChannel. This kind of channel means accept message on the send and perform handling directly just in send process. In the raw Java words it may sound like: call one service from another. Throw NPE if the another hasn't been autowired.
So, if you use DirectChannel for the output, you should declare somewhere a subscriber for it. I don't know what is your logic, but that is how it works and no other choice to fix Dispatcher has no subscribers for channel.
Although you can use some other MessageChannel type. But for this purpose you should read more doc, e.g. Mark Fisher's Spring Integration in Action.

Categories

Resources