Spring integration ip - udp channel with java code only - java

I've been looking at the Spring integration ip module, I wanted to create UDP channel for receiving, but I found I can only do it with XML.
I was thinking that I could make something out if I looked inside the implementation code, but it creates bean definition itself, from parameters supplied in xml.
I can't use xml definitions in my code, is there a way to make it work with spring without xml?
alternatively, is there any better way in java to work with udp?

Starting with version 5.0 there is Java DSL on the matter already, so the code for UDP Channel Adapters may look like:
#Bean
public IntegrationFlow inUdpAdapter() {
return IntegrationFlows.from(Udp.inboundAdapter(0))
.channel(udpIn())
.get();
}
#Bean
public QueueChannel udpIn() {
return new QueueChannel();
}
#Bean
public IntegrationFlow outUdpAdapter() {
return f -> f.handle(Udp.outboundAdapter(m -> m.getHeaders().get("udp_dest")));
}
But with existing Spring Integration version you can simply configure UnicastReceivingChannelAdapter bean:
#Bean
public UnicastReceivingChannelAdapter udpInboundAdapter() {
UnicastReceivingChannelAdapter unicastReceivingChannelAdapter = new UnicastReceivingChannelAdapter(1111);
unicastReceivingChannelAdapter.setOutputChannel(udpChannel());
return unicastReceivingChannelAdapter;
}
In the Reference Manual you can find the Tips and Tricks chapter for some info how to write Spring Integration application with raw Java and annotation configuration.
I added JIRA to address Java sample in the Reference Manual.

Related

Spring AMQP: remove old bindings and queues

I’m using Spring AMQP and Spring Boot #Configuration and #Bean annotations in order to create all required queues, exchanges and bindings.
#Bean
public Queue queue() {
return new Queue("my_old_queue", true, false, false);
}
#Bean
public Exchange exchange() {
return new DirectExchange("MY_OLD_EXCHANGE");
}
#Bean
public Binding binding() {
return BindingBuilder.bind(queue())
.to(exchange())
.with("old_binding")
.noargs();
}
But I’ve faced with a problem of upgrading my topology:
I wanna add a new queue/binding/exchange
And remove an old queue/binding/exchange (even if it was durable entity).
Does some annotation exists for removing or unbinding (like #Unbind)?
I’ve seen the example where RabbitManagementTemplate was suggested, but it’s a completely different way of configuration - I wanna keep everything in the single #Configuration class and use annotations or config beans only (is it possible?).
Does some common pattern exists for creating/removing and updating rabbit topology (maybe I missed something)?
You cannot delete entities with annotations or configuration, use the RabbitAdmin.delete*() methods to remove them like in that answer - the management template was used to list the bindings, the RabbitAdmin (amqpAdmin) does the removals.

Spring AMQP cannot create bean to return a List<Binding>

I am trying to use Spring AMQP, version 2.1.2.release, to create multiple bindings to a topic exchange.
I found this question: How to setup multiple topics in a RabbitMQ Java config class using Spring Framework?
Which seemed to have the answer. I also found the documention which provides the same solution.
However, the Bindings are not being created when I return a List in my Bean. If I return a single Binding, then it does work. I cannot add a comment to that question due to lack of reputation.
Here is my code:
#Bean
public TopicExchange topicExchange() {
return new TopicExchange("topicExchange");
}
#Bean
public Queue testQueue() {
return new Queue("testQueue");
}
#Bean
List<Binding> multipleBindings() {
return Arrays.asList(
BindingBuilder.bind(testQueue()).to(topicExchange()).with("t1"),
BindingBuilder.bind(testQueue()).to(topicExchange()).with("t2"));
}
#Bean
Binding singleBinding() {
return BindingBuilder.bind(testQueue()).to(topicExchange()).with("t3");
}
In this code, I get the "t3" topic binding, but do not see "t1" or "t2" when I look at the Rabbit Management console.
Please help, as this code looks very simple and it follows the documentation. What am I missing?
Thank you
You are referring to very old documentation. According the version you use, there is already a Declarables container instead of List to use: https://docs.spring.io/spring-amqp/docs/2.1.4.RELEASE/reference/#collection-declaration

Java configuration for int-jms:outbound-channel-adapter from spring integration

I am trying to convert a XML based configuration to JAVA based configuration. Can someone please let me know the java annotation based configuration for the following
<jms:outbound-channel-adapter channel="requestChannel"
connection-factory="testConnectionFactory"
destination-name="${jms.queueName}"
message-converter="messageConverter"/>
I tried having a look at this Reference doc. But i am not able to understand how do I map the above xml to the annotation config.
#ServiceActivator(inputChannel="requestChannel")
#Bean
public MessageHandler outbound(JmsTemplate jmsTemplate) {
JmsSendingMessageHandler handler = new JmsSendingMessageHandler(jmsTemplate);
handler.setDestinationName(...);
...
return handler;
}
#Bean
public JmsTemplate jmsTemplate(ConnectionFactory jmsConnectionFactory) {
...
template.setMessageConverter(converter());
return template;
}
Then add the connection factory and converter beans.
EDIT
Also pay attention to Spring Integration Java DSL project, which provides the org.springframework.integration.dsl.jms.Jms Factory on the matter. You can find its usage in the JmsTests: https://github.com/spring-projects/spring-integration-java-dsl/blob/master/src/test/java/org/springframework/integration/dsl/test/jms/JmsTests.java

Bean casting error from nested injections

I am working with Spring Integration with my project right now, specifically with MessageChannel/PublishSubscribeChannel. What I am trying to achieve is to create a broker module, so that other part of the system can call this module to send message to a specific MessageChannel.
Here is what I am doing now in the broker module:
#Configuration
public class BrokerConfiguration {
#Bean
public MessageChannel brokerChannel1() {
return new PublishSubscribeChannel();
}
}
and:
#Component
public class BrokerA {
#Autowired
#Qualifier("brokerChannel1")
public MessageChannel messageChannel;
public void sendAMessage() {
messageChannel.send(MessageBuilder.withPayload("This is a message!").build());
}
}
I have played around this setup by creating a SpringBootApplication within the broker module and it seems to work perfectly fine. However, when I try to use it in a different module of my system like this:
#Autowired
private BrokerA brokerA;
public void doSomethingHere() {
brokerA.sendAMessage();
}
I get a ClassCastException like this:
java.lang.ClassCastException: org.springframework.integration.channel.PublishSubscribeChannel cannot be cast to org.springframework.messaging.MessageChannel
And when I change messageChannel in BrokerA to the type of PublishSubscribeChannel, it will complain about PublishSubscribeChannel doesn't have a method called send().
This really baffles me. Any suggestions or comments? Thank you!
You have an old version of Spring Integration on the classpath; MessageChannel etc was moved from o.s.integration... to o.s.messaging in Spring 4.0.
You need to use Spring Integration 4.x.
Check your classpath, probably you have duplicated jars.
I ran your code on my environment with last spring boot version without any version specification about spring and it's working just right, the only error is on
MessageBuilder.withPayload("This is a message!") it should be MessageBuilder.withPayload("This is a message!").build()
And I verified using org.springframework.integration.support.MessageBuilder.
Try doing an explicit cast in the return statement of brokerChannel1() in BrokerConfiguration.

inbound and Outbound Gateway AMQP annotation

I have a working spring integration + rabbitmq application using xml config. Now, i am converting them to java config annotation. There are available classes and java annotation for some main amqp objects like Queue , TopicExchange , and Binding. However, I cant find any reference in converting inbound-gateway and outbound-gateway to java annotation or class implementation.
Here's my implementation:
// gateway.xml
<int-amqp:outbound-gateway request-channel="requestChannel" reply-channel="responseChannel" exchange-name="${exchange}" routing-key-expression="${routing}"/>
<int-amqp:inbound-gateway request-channel="inboundRequest"
queue-names="${queue}" connection-factory="rabbitConnectionFactory"
reply-channel="inboundResponse" message-converter="compositeMessageConverter"/>
Is it possible to convert them to java annotation or class implementation(bean, etc..)?
ADDITIONAL: I am currently using spring boot + spring integration.
Would be great, if you take a look into Spring Integration Java DSL.
It provides some fluent for AMQP:
#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(Amqp.channel("amqpOutboundInput", this.rabbitConnectionFactory))
.handle(Amqp.outboundAdapter(this.amqpTemplate).routingKeyExpression("headers.routingKey"))
.get();
}
From annotation perspective you should configure something like this using classes from Spring Integration directly:
#Bean
public AmqpInboundGateway amqpInbound() {
AmqpInboundGateway gateway = new AmqpInboundGateway(new SimpleMessageListenerContainer(this.rabbitConnectionFactory));
gateway.setRequestChannel(inboundChanne());
return gateway;
}
#Bean
#ServiceActivator(inputChannel = "amqpOutboundChannel")
public AmqpOutboundEndpoint amqpOutbound() {
AmqpOutboundEndpoint handler = new AmqpOutboundEndpoint(this.rabbitTemplate);
handler.setOutputChannel(amqpReplyChannel());
return handler;
}

Categories