In order to learn Spring Integration, I understood the sample provided by Spring Project and reimplemented it + arranged it. This article is a memorandum. So I think there are various mistakes, but I would appreciate it if you could point out that point. The sample is registered in the following Git. spring-integration-sample
This time about _ ** Gateway ** _ which is one of basic jms. By the way, the version of Spring Integration is `` `4.3.10.RELEASE```.
Three functions are implemented in JMS, and when the Main class is executed, it interactively decides which mode 1 to 3 to try. This time, we implemented only Gateway 1.
There are many things that I do not understand at all, and it is difficult to understand even if it is implemented on one side, so instead of implementing it in the same format, I will implement it individually and understand it.
Gateway
The overall flow is probably as follows. (Please point out if you make a mistake)
Standard input(stdin) -> stdintojmsoutchannel -> requestqueue -> serviceactivator -> requestchannel -> replyqueue -> replychannel ->Standard output(stdout)
outbound-gateway
packs the value entered from the console into the queue (`RequestQueue```) via
stdin-channel-adapter```. Next, ```inbound-gateway``` gets the value from ``
RequestQueueand processes it with
ServiceActivator and sends it to `` `RequestChannel
. It also gets outbound-gateway
from `` `ReplyQueue, relays to
ReplyChannel```, and finally does standard output.
Outbound-gateway in Reference Manual In the explanation, ReplyQueue
(`reply-destination``` attribute) can not be specified, otherwise
TemporaryQueue``` will be used. Since it is not specified in this sample, it seems that the value is sent from ``
TemporaryQueue to `` `ReplyChannel
.
This sample consists of 3 configurations: common.xml, outboundGateway.xml, and inboundGateway.xml. What I implemented is a reuse of the basic sample project, but I have omitted all the descriptions that seem unnecessary for understanding.
Here, the settings required for aggregation, channelAdapter, and other functions are defined as common settings, but this time, only the settings required for the gateway are left.
The following settings are required for the Gateway app. The `connectionFactory`
of 1 is required internally by the `JmsOutboundGateway``` class to create a connection. 2 seems to be needed for ``` stdin-channel-adapter``` to poll standard input. And since
`requestQueueis used by both _outboundGateway_ and _inboundGateway_, it needs to be defined. Here, the OSS
ActiveMQ``` Queue is specified as the implementation class.
Other settings seemed unnecessary this time, so I deleted them.
<!-- 1 -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost"/>
</bean>
</property>
<property name="sessionCacheSize" value="10"/>
</bean>
<!-- 2 -->
<bean id="requestQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="queue.demo"/>
</bean>
<!-- 3 -->
<integration:poller id="poller" default="true" fixed-delay="1000"/>
Only the minimum necessary settings are left here as well. There was also a setting of profile information for test, but I deleted it because it is unnecessary first.
Here, the JmsOutboundGateway
class plays a role of relaying various processing flows as its name suggests, so the settings required for relaying are described.
Where 1 and 3 define the inputs and outputs to the console. 2 passes the input information obtained from the request-channel
attribute to the
send method of the` `requestQueue (MessageChannel)` `. The return value goes into the `` `TemporaryQueue
which is omitted this time, so it seems that it is set to pass it internally to the object of the `` `reply-channel``` attribute.
<!-- 1 -->
<stream:stdin-channel-adapter id="stdin" channel="stdinToJmsoutChannel"/>
<channel id="stdinToJmsoutChannel"/>
<!-- 2 -->
<jms:outbound-gateway request-channel="stdinToJmsoutChannel"
request-destination="requestQueue"
reply-channel="jmsReplyChannel"/>
<!-- 3 -->
<channel id="jmsReplyChannel" />
<stream:stdout-channel-adapter channel="jmsReplyChannel" append-newline="true"/>
At the end, it will be inbound setting, but originally there was `` `ServiceActivator``` setting, but it was also implemented in the article of Hello World So I decided to implement it with annotations. By using annotations, it became easier to understand what you want to do with xml. (Since Spring Integration tends to make xml complicated, I thought for a moment that it would be better to implement it mainly with JavaConfig or annotations, but as the scale of the application grows, I think that the source code suddenly becomes difficult to follow. . It seems to be more difficult to adjust the spoon than the web system.)
Returning to the main topic, 1 is doing a component scan. This eliminates the need for bean definition for classes that implement `ServiceActivator```. Next, 2 defines the internal processing flow with the ```inbound-gateway``` tag. Contrary to outbound, the value is acquired from the ``` request-destination``` attribute and propagated to the
`request-channel``` attribute.
<!-- 1 -->
<context:component-scan base-package="org.ek.sample.jms.gateway"/>
<!-- 2 -->
<jms:inbound-gateway id="jmsin"
request-destination="requestQueue"
request-channel="requestChannel"/>
<channel id="requestChannel"/>
ServiceActivator
As mentioned above, ServiceActivator
used annotations. For that purpose, (1) @ EnableIntegration
annotation and (2) @MessageEndpoint
annotation are used.
If you use `` `@ ServiceActivator``` without using (1), you will get an error like the Dispatch destination cannot be found. I just made a simple recognition that it is necessary to add annotations together to use annotations with Endpoint type objects. I'd like to see the contents a little later, but for now I'll put up with it and move on.
(2) is just an annotation to make it a component scan target. It is the same as `@ Controller``` or
`@ Service``` on the web.
(3) has just replaced the bean definition.
@EnableIntegration // (1)
@MessageEndpoint // (2)
public class GatewayEndpoint {
// (3)
@ServiceActivator(inputChannel="requestChannel")
public String upperCase(String input) {
return "JMS response: " + input.toUpperCase();
}
}
The code for the Main class is as follows. Just define xml as an array and load it as an instance of ApplicationContext. With this alone, the interaction between the console and the application can be realized.
private final static String[] configFilesGatewayDemo = {
"/META-INF/spring/integration/common/common.xml",
"/META-INF/spring/integration/gateway/inboundGateway.xml",
"/META-INF/spring/integration/gateway/outboundGateway.xml"
};
@SuppressWarnings("resource")
public static void main(String[] args) {
new ClassPathXmlApplicationContext(configFilesGatewayDemo,GatewayMain.class);
}
This time I dealt with inbound-gateway and outbound-gateway, but I thought it would be quite easy to use because they do good in and out exchanges on the back side. After that, I personally can't read xml sensuously, so I had the impression that I would forget it later even if I implemented it myself, unless I thought about how to improve the readability there.
Click here for the code. Tweaked Jms sample
Recommended Posts