Not able to connect localstack with spring clound - java

I have setup locastack in my local pc. I am able to create, send and receive in the queue using command line.
How am trying to connect SpringBoot application with the localstcak queue.
I am not finding any tutorial which will guide me how we can read data from localstack queue using spring cloud.
I have a class which looks like this
#Component
#Profile("aws")
public class EventListener {
private static final Logger LOGGER = LoggerFactory.getLogger(VisitsQueue.class);
#Value("${sqs.queuename}")
private String queueName;
private ObjectMapper mapper = new ObjectMapper();
#RuntimeUse
#SqsListener("${sqs.queuename}")
public void receiveMessage(String message, #Header(value = "SenderId", required = false) String senderId,
#Headers Map<String, Object> allHeaders) {
LOGGER.info("Received message with content {}", message);
}
}

Related

How to delegate Spring Integration Message Payload to Spring Batch Job?

I have an FTP Streaming Inbound Channel Adapter from Spring Integration which produces message with payloads of type InputStream, letting files be fetched without writing to the local file system.
#Bean
#InboundChannelAdapter(channel = Constants.CHANNEL_INBOUND_FTP_ADAPTER, poller = #Poller(fixedDelay = Constants.FIXED_POLLING_FROM_INBOUND_FTP_ADAPTER_DELAY))
public MessageSource<InputStream> ftpMessageSource() {
FtpStreamingMessageSource ftpStreamingMessageSource = new FtpStreamingMessageSource(ftpRemoteFileTemplate());
ftpStreamingMessageSource.setRemoteDirectory(ftpConnectionParameters.getRootDir());
ftpStreamingMessageSource.setFilter(chainFileListFilter());
ftpStreamingMessageSource.setMaxFetchSize(Constants.INBOUND_ADAPTER_MAX_FETCH_SIZE);
return ftpStreamingMessageSource;
}
After I transform with
#Bean
#org.springframework.integration.annotation.Transformer(inputChannel = Constants.CHANNEL_INBOUND_FTP_ADAPTER, outputChannel = Constants.CHANNEL_STREAMED_DATA)
public Transformer transformer() {
return new StreamTransformer(Charset.defaultCharset().name());
}
Then handle data to check it works and maybe for custom inteceptors for future:
#ServiceActivator(inputChannel = Constants.CHANNEL_STREAMED_DATA, outputChannel = "BATCH_ALARM_CHANNEL")
public Message<?> alarmHandler(Message<?> message) {
System.out.println(Constants.CHANNEL_ALARM);
System.out.println(message.getHeaders());
return message;
}
After this according to official Spring Batch Integration documentation I have one more Transformer which let us transform to JobLaunchRequest
#Transformer
public JobLaunchRequest toRequest(Message<File> message) {
JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
jobParametersBuilder.addDate("dummy", new Date());
return new JobLaunchRequest(job, jobParametersBuilder.toJobParameters());
}
Here we have Message from last BATCH_ALARM_CHANNEL which needs in Spring Batch Jobs, but JobParametersBuilder doesn't allow to put complex object only primitive types. So how I can pass message payload for JobLaunching and do the rest of the work such as read, parse and save to DB?

WebSocket subscription not receiving message when using MappingJackson2MessageConverter

I would like to subscribe and receive any events using objects instead of strings when using Spring Boot WebSockets. If my method returns a string and I use the StringMessageConverter my code successfully listens for the /topic/rooms/created event.
If I return a Room object instead and use MappingJackson2MessageConverter then my subscription no longer receives any messages.
#MessageMapping("/rooms/create/{roomName}")
#SendTo("/topic/rooms/created")
#CrossOrigin(origins = "http://localhost:3000")
public Room createRoom(#DestinationVariable final String roomName) {
return roomService.createRoom(roomService.getRooms().size(), roomName);
}
This sends the message and creates the room successfully. The response isn't picked up by the subscription.
final String roomName = "RoomName";
final StompSession.Subscription subscription = stompSession.subscribe("/topic/rooms/created", new StompFrameHandler() {
#Override
public Type getPayloadType(final StompHeaders headers) {
return Room.class;
}
#Override
public void handleFrame(StompHeaders headers, Object payload) {
// Not called
System.out.println("Received message");
}
});
System.out.println("Sending message");
stompSession.send("/app/rooms/create/" + roomName, null);
I've also tried creating a Room instance and using a jackson object mapper to convert to JSON with no issues.
How can I resolve this?

Springboot Websocket Client to read messages from a Websocket stream with different port

I am new to both springboot and websockets so please be gentle and this is my last question chance on this account. I have a websocket jar that sends messages from two urls ws:localhost/operations and ws:localhost/prices from 8080 port. My task is to read those messages. The Jar file streams messages like:
For operation:
"data":{ "description":"lorem ipsum", "id":"OJ1136453723" },
"type":"DELETE"
For price:
"data":{ "price":1384.1685, "id":"WN6427148286" }, "type":"PRICE"
I have spring-boot-starter-websocket, spring-boot-starter-security and lombok as dependencies.
I seem to be connecting to the jar file, because powershell says "Socket connected
Frame TEXT (fin=true, buffer len = 48)" when I run my code but it only hits the Application breakpoints whenever I debug, it doesnt even go to controller or config classes. It may be an obvious mistake but I am a bit lost so any help would be appriciated. Also, my port for this client is 8443 which is specified in application.yml and it starts there.
My Client:
public class WSClient{
private static String URL = "ws://localhost:8080";
public static void main(String[] args) throws Exception {
WebSocketClient client = new StandardWebSocketClient();
WebSocketStompClient stompClient = new WebSocketStompClient(client);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
StompSessionHandler sessionHandler = new MyStompSessionHandler();
stompClient.connect(URL, sessionHandler);
new Scanner(System.in).nextLine();
}
Controller:
#Controller
public class MsgController {
#Autowired
private SimpMessagingTemplate simpMessagingTemplate;
#MessageMapping("/operations")
public Operations operations(Operations operations)throws Exception{
System.out.println(operations);
simpMessagingTemplate.convertAndSend("/operations", operations);
return operations;
}
StompSessionHandler:
public class MyStompSessionHandler extends StompSessionHandlerAdapter {
private Logger logger = LogManager.getLogger(MyStompSessionHandler.class);
#Override
public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
logger.info("New session established : " + session.getSessionId());
session.subscribe("/operations", this);
System.out.println("Subscribed to /operations");
logger.info("Subscribed to /operations");
}
#Override
public void handleException(StompSession session, StompCommand command, StompHeaders headers, byte[] payload, Throwable exception) {
logger.error("Got an exception", exception);
}
#Override
public Type getPayloadType(StompHeaders headers) {
return Operations.class;
}
#Override
public void handleFrame(StompHeaders headers, Object payload) {
Operations ops = (Operations) payload;
System.out.println(ops);
}
}
Operations:
#lombok.Data
public class Operations{
public String description;
public String id;
public String type;
}
EDIT:
Thanks to help of #OkanKonur the problem is that StompHandler's afterConnected is not called even though it seems like they are connected. We tried it with the github link he's given in the comments and it seems to work. The jar file is most probably not a spring project so is there a way to solve this? It still can't read anything.

Spring cloud stream RabbitMQ routing messages dynamically

I have implemented the example as shown here Spring Dynamic Destination
In the rabbitmq, it is creating an exchange dynamically, but there is no option to provide binding or routing key. My requirement is to send a message to this dynamically created exchange with a routing key. How would i need to implement this to setup the routing key?
#Component
public class DDProducerBean {
#Autowired
private BinderAwareChannelResolver poChannelResolver = null;
public void publish(DDSocketVO ddSocketVO) throws Exception {
this.poChannelResolver.resolveDestination(ddSocketVO.getDestination()).send(MessageBuilder.withPayload(new ObjectMapper().
setVisibility(PropertyAccessor.FIELD, Visibility.ANY).
writeValueAsString(ddSocketVO)).build());
}
}
Here is the workaround as suggested Here
Basically create a MessageChannel with the dynamic destination using BinderAwareChannelResolver, then connect to RabbitMQ with RabbitAdmin API and bind the newly created exchange to another queue or exchange with routing key before sending messages.
#Autowired
private BinderAwareChannelResolver poChannelResolver;
public void publish(WebSocketVO webSocketVO) throws Exception {
MessageChannel channel = this.poChannelResolver.resolveDestination(webSocketVO.getDestination());
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setUsername(System.getProperty("spring.cloud.stream.binders.corerabbit.environment.spring.rabbitmq.username"));
connectionFactory.setPassword(System.getProperty("spring.cloud.stream.binders.corerabbit.environment.spring.rabbitmq.password"));
connectionFactory.setAddresses(System.getProperty("spring.cloud.stream.binders.corerabbit.environment.spring.rabbitmq.addresses"));
connectionFactory.setVirtualHost(System.getProperty("spring.cloud.stream.binders.corerabbit.environment.spring.rabbitmq.virtual-host"));
AmqpAdmin amqpAdmin = new RabbitAdmin(connectionFactory);
TopicExchange sourceExchange = new TopicExchange(webSocketVO.getDestination(), false, true);
TopicExchange destExchange = new TopicExchange("amq.topic");
amqpAdmin.declareBinding(BindingBuilder.bind(destExchange).to(sourceExchange).with(webSocketVO.getRoutingKeyExpression()));
channel.send(MessageBuilder.withPayload(new ObjectMapper().
setVisibility(PropertyAccessor.FIELD, Visibility.ANY).
writeValueAsString(webSocketVO)).build());
amqpAdmin.deleteExchange(webSocketVO.getDestination());
connectionFactory.destroy();
}

Akka Camel websocket client producer

I am trying to communicate with a websocket server using Apache Camel AHC-Websocket Component with Akka Camel in Java. In this case, websocket endpoint is goint to be a well known websocket public service.
Using:
JDK 8.x
Akka Java API with Akka Camel, Akka Actor and Akka SLF4J 2.3.9
Apache Camel with AHC WS Component 2.14.1
I followed Akka Camel tutorial for Java located over here.
Short description: Every response received by UntypedProducerActor when I make a request returns CamelMessage with body field as null. But when I make request via ProducerTemplate I receive correct response.
Long description: I am getting strange behaviour from Akka Camel when I make a request and expect a response from the websocket endpoint. When I make a request to the endpoint via defined ActorRef, for example like so:
ActorRef wsProducer = getContext().actorOf(SimpleProducer.props("ahc-ws:echo.websocket.org"));
final Timeout timeout = new Timeout(3, TimeUnit.MINUTES);
final Future<Object> future = Patterns.ask(wsProducer, "Please, respond!", timeout);
final Object result = Await.result(future, timeout.duration());
I clearly see in the logs that Apache Camel websocket endpoint received a response:
DEBUG o.a.c.component.ahc.ws.WsEndpoint - received message --> Please, respond!
But the result object will be a CamelMessage with body field always set to null. The same CamelMessage present in public Object onTransformResponse(Object message) method of my SimpleProducer.
However, when I make request via ProducerTemplate like this:
final Camel camel = CamelExtension.get(getContext().system());
final CamelContext context = camel.context();
final ProducerTemplate template = camel.template();
Object result = template.requestBody("ahc-ws:echo.websocket.org", "Alpha is there!");
It works and result will contain correct response body: "Alpha is there!".
My SimpleProducer is pretty much the same as in tutorial:
public class SimpleProducer extends UntypedProducerActor {
private final LoggingAdapter LOG = Logging.getLogger(getContext().system(), this);
private final String mEndpointUri;
public SimpleProducer(final String serverUrl) {
mEndpointUri = serverUrl;
}
#Override
public String getEndpointUri() {
return mEndpointUri;
}
#Override
public Object onTransformResponse(Object message) {
return super.onTransformOutgoingMessage(message);
}
#Override
public boolean isOneway() {
return false;
}
public static Props props(final String endpointUri) {
return Props.create(new Creator<SimpleProducer>() {
private static final long serialVersionUID = 1L;
#Override
public SimpleProducer create() throws Exception {
return new SimpleProducer(endpointUri);
}
});
}
}
Maybe somebody had the same issue and can help me out?

Categories