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

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

Related

Spring xml config equivalent to #Order

Given the following Java class
#Order(12)
#Component
public class MyComponent {
//....
}
what is the equivalent in the Spring XML configuration? I couldn't find anything matching the #Order annotation for the XML based configuration:
<bean class="MyComponent" />
In spring you have 2 choices:
annotation
interface implementation
In your case you will have to go with the second option.
Your class needs to implement Ordered, but this will bind your class with spring API. It's same when using annotation over class.
But if you are using configuration classes, instead of xml config, then you can have plain java beans, and keep all Spring API in configurations.
Example:
#Bean(destroyMethod = "shutdown")
#Order(12)
public ScheduledExecutorService scheduledExecutorService() {
return Executors.newSingleThreadScheduledExecutor();
}
Configuration classes give you the option to separate Spring API(annotations) from your beans.

Spring integration ip - udp channel with java code only

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.

Is it possible to write a Guice-like module in Spring Framework with Java configuration?

I was wondering if there was a sort of compromise that allowed you to emulate/leverage the Google Guice style EDSL way of writing modules which binds interfaces to implementations in Spring.
For example, say I had a Google Guice Module that looked like this:
public class BillingModule extends AbstractModule {
protected void configure() {
bind(BillingService.class).to(RealBillingService.class);
}
}
This binds the BillingService interface to the RealBillingService implementation.
One way that I think I can do utilizing Spring's Java configuration class is something that looks like this
#Configuration
public class BillingConfiguration {
#Bean
public BillingService getRealBillingService() {
return new RealBillingService();
}
}
I was wondering if there was a better way to do this or if this broke down with increasingly complex usage.
I really like Google Guice and how it does Dependency Injection but that's kind of all it does. Spring does a lot more (yes, its dependency injection mechanism is still not 'as-nice' as Guice) but undeniably has some great projects that we would like to utilize like Spring Data, Spring Data REST, etc. which eliminate the need for writing a ton of boilerplate code.
The way to do this is to use #Profile to include different implementations of the same interface.
A simple example would be DataSource. This can however easily be extended to any other interfaces with multiple implementations.
As an example:
#Configuration
public class LocalDataConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
}
}
and then for use in production:
#Configuration
#Profile("production")
public class JndiDataConfig {
#Bean
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
Then all you need to do is declare which profiles are active when you start your application context and #Inject/#Autowire DataSource where you need it.
I've used both Guice and Spring a fair bit. As far as I know, the spring usage you show in the question is the only way to achieve the same as the binding in Guice with Spring. If you need to inject dependencies you can always include those as arguments to the #Bean method and have spring inject them for you.
It's definitely not as clean but it works the same way. One key thing to watch out for is that the default scope in spring is Singleton rather than a new instance every time (spring calls this scope prototype)

Annotation equivalent of <tx:jta-transaction-manager/> for Java EE environments

How can I achieve something similar to this:
<jee:jndi-lookup id="datasSource"
jndi-name="jdbc/dataSourceName" expected-type="javax.sql.DataSource" />
<tx:jta-transaction-manager/>
Using annotations?
#Configuration
#EnableTransactionManagement
public class AppConfig {
#Bean
public DataSource dataSource() {
// What goes here?
}
#Bean
public PlatformTransactionManager txManager() {
// What goes here?
}
}
I've seen a lot of examples with DataSourceTransactionManager and BasicDataSource, but I couldn't find a equivalent annotation driven configuration (that finds the container UserTransaction, etc).
The only way I am aware of is to replicate the behavior of namespace parsers of these custom namespaces.
So, <jee:jndi-lookup> is handled by org.springframework.ejb.config.JndiLookupBeanDefinitionParser and ultimate creates a bean which is an instance of JndiObjectFactoryBean with the passed in attributes.
Similarly, <tx:jta-transaction-manager/> is handled by org.springframework.transaction.config.JtaTransactionManagerBeanDefinitionParser and based on the runtime environment, returns a specific instance of class.
A neat feature of Spring 4 that you can use is #Conditional(reference here). With #Conditional and using a Spring-Boot Conditional implementation called ConditionalOnClass(reference here), you can replicate the behavior of <tx... something like this:
#Configuration
#ConditionalOnClass(name="weblogic.transaction.UserTransaction")
public class WebLogicTxMgrConfig {
#Bean
public JtaTransactionManager txManager() {
return new WebLogicJtaTransactionManager();
}
}
I know this is not a complete answer, but hopefully should help you create the relevant configuration.

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