Spring Cloud Stream - Send and receive synchronized - spring-boot

In my spring boot rest controller, I'm using StreamBridge for sending a message to the rabbitMQ server with something like
streamBridge.send("consumer-in-0", "hello world");
Is there a way to do a send and wait the response ?

Alright, as I said, late to the party, but there seems to be a way. simply you can make the producer synchronous, this can be done in application.properties as such:
spring.cloud.stream.kafka.bindings.functionName-out-0.producer.sync=true
The same configuration was originally working for the MessageChannel pre Spring cloud function, but as I understand the underlying functionality is already the same

Related

Spring Cloud Stream RabbitMQ wait for publisher confirms

I am using Spring Cloud Stream with the RabbitMQ binder. I use the StreamBridge to send messages to a destination. I want to send a message with StreamBridge and after that synchronously wait for the publisher confirm (to make sure the message was received by the broker). Is that possible using Spring Cloud Stream? I have found the RabbitTemplate's waitForConfirms method and i have publisherConfirmType: simple and publisherReturns: true set in my configuration. But i don't know how to access the method with the RabbitTemplate since i don't use it because i'm using the StreamBridge. If i Autowire a RabbitTemplate and call waitForConfirms after my StreamBridge send call, it waits forever (nothing happens). I'm looking for an option like with the Kafka binder. There you can set the Producer to "sync" and "requiredAcks" to 1 to wait for publisher acks.
Thanks for any help!

How to produce and consume a RabbitMQ message with inside Spring RestController and send it back to the user

Hello Anyone and Everyone. I am working on a Spring Boot application. Here is my problem. I have a Spring RestController with a post-mapping that takes in some data. I am then needing to send that data over RabbitMQ to another application which in return will perform some calculations on that data and then send it back to me which I then want to return back to the user.
I know that RabbitMQ is for async communication. But I need my controller to return the result that comes back from RabbitMQ all in one go. Right now I am using.
#EnableBinding(Sink::class)
class OptimizedScheduleMessageListener {
#StreamListener(Sink.INPUT)
fun handler(incomingMessage: MyDTO) {
println(incomingMessage)
}
}
to retrieve the results from RabbitMQ. Now I just need my Controller to return it.
#PostMapping( produces = ["application/json"])
fun retrieveOptimizedSchedule: Result<MyDTO> {
myUncalculatedDTO: MyDTO()
source.output().send(MessageBuilder.withPayload(myUncalculadeDTO).build())
return ???
}
Any help with this endeavor is much appreciated.
Thanks in Advance.
Spring Cloud Stream is not designed for request/reply processing.
See the Spring AMQP (Spring for RabbitMQ) project.
The RabbitTemplate has sendAndReceive and convertSendAndReceive methods to implement the RPC model.
On the server side, a #RabbitListener method can be used for request/reply.
What you are trying to do is not advised for couple of reasons.
1. The failure of the 'Another application' which consumes the Rabbit
MQ messages will result in Requests being blocked on the controller end.
2. There is a limit on how many requests you can have simultaneously from the server to clients.
What you can do is use any other communication protocol than REST for this specific part. May be Websocket will be an ideal solution. If not you need to have two REST endpoints. One to submit and get back an request-id, another to poll periodically with the request-id and get processed, completed response.

Spring integration : handle a File given in arguments

I have an existing Spring Integration app, which handle files coming from FTP with InboundChannelAdapter. I want to plug Spring boot to this app to use it now like this :
java -jar app.jar <filetohandlepath>
So, the application start with this command, and stop at the end of the treatment. But my question is how can I run my existing channels (ServiceActivator) to give this file to handle ?
I can use an InboundChannelAdapter, but I think the poller can be a problem
Maybe a Gateway ? But I don't think this can be a solution
Or I need to build and send a Message manually ?
What about Spring Boot, to handle the argument ? I need to build the message into the main method, or in an other class with a scan ?
I just need to know the best way to design my app.
Your FTP Inbound Channel Adapter polls remote file to local files and sends them as payload of messages into some channel for the mentioned Service Activator. Of course you can send message manually to the same channel with the payload accepted by that Service Activator subscriber. Yes, you can use #MessagingGateway to separate Messaging concern from your code. Or you can just rely on the MessagingTemplate and its convertAndSend() API. Any convenient way for you is acceptable: https://docs.spring.io/spring-integration/docs/5.0.4.RELEASE/reference/html/messaging-endpoints-chapter.html#gateway
As for Spring Boot and command line arguments, you definitely can take a look into the CommandLineRunner: https://docs.spring.io/spring-boot/docs/2.0.1.RELEASE/reference/htmlsingle/#boot-features-command-line-runner

Sending message from Spring Kafka to Angular

Is there a way to send message from Spring Kafka to Angular without using Websocket?
I use Spring as service side, and Angular as Client side.
When, I send a Kafka message from Spring server-side, I just want to transmit this message to Angular based client side.
I used this code in Spring-server to send message:
kafkaTemplate.send(topic, payload);
Actually my question is nearly same of this:
Actually my question is nearly same of this:
Receiving Kafka event on web browser real time
You can use Kafka REST API (proxy), it lets you to call Kafka directly from you client javascript and so you could consume/send events directly.
Have a look: https://github.com/confluentinc/kafka-rest

Camel routes from activemq to rest endpoint

I am trying to use Spring Boot 1.5.2.RELEASE + Camel (Spring Boot starter) 2.19.2 to listen to ActiveMQ queue and then post the message to a rest endpoint URL (POST method) as its body. What would be the best possible way to achieve this?
I have gathered pieces of information and am trying to tie it all together but getting a bit confused.
Here is what I have gathered for Camel Rest DSL, I am not too sure if camel below is creating these rest services via this or is it just an already exposed endpoint, in my case it is an already exposed endpoint
rest("/basePath")
post("/someEndpoint").to("direct:restEndpoint")
Using the above is what I have gathered for ActiveMQ which I am not too sure is correct
from("activemq:queue:<queue_name>").to("direct:restEndpoint")
But again, I am not too sure how to listen to the ActiveMQ queue for new messages or is it something that Camel would do by default always? Additionally, I need to pass the message as a post body to my rest endpoint. I also saw some references to camel-http4 and camel-http as well and I am completely confused.
Any assistance would be greatly appreciated.
Some confusion is common when starting to use Camel, but your final solution will look something like:
from("activemq:queue:my-route")
.process(/* change the in/out messages if you need to */)
.to("http4://your-endpoint.com");
Don't try to simply copy/paste this code until it works. My Camel rule of thumb is: always read the component documentation and try playing with it using it in your software. In your case I suggest:
Read ActiveMQ component docs and try reading from ActiveMQ / writing to a Log;
Generate some input from a Timer and send to your Rest endpoint using HTTP4 Component;
Your first routes will take some time for simple things but you will get on flow quickly.

Resources