Hello
1.
The source is always null at the other end
But don't send to the external system any Java object. Where is a guaranty, that other side is Java too and the more it has in its CLASSPATH the same class for deserialization?
Messaging is just middleware. It doesn't have any ability to work with buisiness objects. It just allows you to transport data between different systems via many existing protocols. To connect these protocols with messaging system there are some specific components - channel adapters.
One of them is <int-event:inbound-channel-adapter/> which allows to listen an ApplicationEvent from the context and sends a Message into Spring Integration Bus. Inside this Bus Messages can contain in their payload any Object including your business object even without the implements Serializable. Because your classes and Spring Integration components are inside the same CLASSPATH of your application. But sending Message to the external system is a bit different and more complex. Here we should think about protocol, framework abilities and the more about data. The last one isn't important for messaging system, but the data has to be understandable for system, which will read this data from messaging system on the other side. So, here we should use some common types of data presentation: XML, JSON or simple String, it can be byte[] too. They can be transported on wires to
messaging system (AMQP) and can be stored until consumer reads it from messaging system.
Spring Integration architecture & design allow easy build the messaging application which can connect to the external systems by the same way as internally between business services. It sometimes confuses developers. Please, take a look into my presentation on the slide 11: http://www.slideshare.net/artembilan...n-but-not-only to figure out how it works inside the Spring Integration application.
2.
how does connecting the
Channel Adapters for both ApplicationEvents and RabbitMQ
manage that
Manage what? It doesn't matter: <int-event:inbound-channel-adapter/> receives event and send a Message into a <channel>. This chennel has subscriber in the face of <int-amqp:outbound-channel-adapter/>. The last one connects to the AMQP-Broker and sends AMQP-Message to the external queue. And that's all: everithing works at the same thread.
On the Consumer application, via your use-case, components are working as unmirrored.
Here is the test-case as I undersatand your use-case:
Sender:
HTML Code:
<rabbit:connection-factory id="rabbitConnectionFactory" />
<rabbit:admin connection-factory="rabbitConnectionFactory" />
<rabbit:queue name="eventsQueue"/>
<rabbit:template id="amqpTemplate" connection-factory="rabbitConnectionFactory"/>
<int-event:inbound-channel-adapter channel="amqpChannel" payload-expression="source"
event-types="com.my.EventAmqpTests$TestEvent"/>
<amqp:outbound-channel-adapter id="amqpChannel" routing-key="eventsQueue" />
Receiver:
HTML Code:
<rabbit:connection-factory id="rabbitConnectionFactory"/>
<channel id="eventsQueue"/>
<amqp:inbound-channel-adapter channel="publishEventChannel" queue-names="eventsQueue"/>
<int-event:outbound-channel-adapter id="publishEventChannel"/>
<beans:bean class="com.my.EventAmqpTests$TestListener"/>
Test class:
Code:
public class EventAmqpTests {
private final static String TEST_MESSAGE = "Hello through AMQP!";
private final static CountDownLatch latch = new CountDownLatch(1);
@Test
public void send() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("EventSender-context.xml", EventAmqpTests.class);
ctx.publishEvent(new TestEvent(TEST_MESSAGE));
}
@Test
public void receive() throws InterruptedException {
new ClassPathXmlApplicationContext("EventReceiver-context.xml", EventAmqpTests.class);
assertTrue(latch.await(2, TimeUnit.SECONDS));
}
public static class TestEvent extends ApplicationEvent {
public TestEvent(Object source) {
super(source);
}
}
public static class TestListener implements ApplicationListener<MessagingEvent> {
@Override
public void onApplicationEvent(MessagingEvent event) {
assertEquals(TEST_MESSAGE, event.getMessage().getPayload());
latch.countDown();
}
}
}
For a better understanding of how it works, please, invoke send() & receive() methods independently: call send() and take a look how it is on Rabbit via his console. Then call receive() and you'll see that ApplicationEvent is received and message disappeared from queue on Broker.
Is it what are you looking for?
Cheers,
Artem
P.S. Sorry, If I was a wordy...