I want to create a socket channel with a rendezvous queue where a client and server can exchange a simple message.
But I already fail to convert the following xml to annotation based spring-4 configuration:
<int:channel id="rendezvousChannel"/>
<int:rendezvous-queue/>
</int:channel>
How would this look like in spring 4?
The short answer:
#Bean
public PollableChannel rendezvousChannel() {
return new RendezvousChannel();
}
Can you explain why it was an issue for you to find the solution from your side?
Any XML component is backed by some Java class anyway and most cases their names reflect the XML component names.
Related
I've an XML config for mail service in spring, that I'd like to transform to JAVA config.
XML Looks like this
<int:chain id="chain"
input-channel="outMailError"
output-channel="outMailEntry">
<int:poller max-messages-per-poll="1" fixed-rate="20000" />
<int:transformer ref="mailSendErrorTransformer" />
</int:chain>
<int:channel id="outMailError">
<int:queue capacity="500" />
</int:channel>
<int:channel id="outboundMailEntry" />
I was able to convert the channels to
#Bean
public DirectChannel outboundMailEntry() {
return new DirectChannel();
}
#Bean
public QueueChannel outboundMailErrorChannel() {
return new QueueChannel(500);
}
But I don't know how to the same for int:chain. I was able to debug and find out what type of bean does spring instantiate for "chain" part of xml - it is PollingConsumer that takes 2 params PollableChannel inputChannel, MessageHandler handler.
The first one is not a problem since I already have that, it is the
#Qualifier("outMailError")
QueueChannel channel
But I do not know about the second one... Spring itself initializes some MessageHandlerChain but I was unable to to set the outMailEntry to it and also dont know about the poller and transformer.. any ídeas?
There is no chain equivalent in Java Config. It was designed especially for XML to let to minimize XML coding.
On the other hand it doesn't look like you need that <chain> at all: you have only one <int:transformer> over there.
In Java Config you would use a #Trasnoformer annotation on your mailSendErrorTransformer method with appropriate inputChannel and outputChannel attributes. The <int:poller> equivalent is also present over there as a poller attribute with resective #Poller configuration.
See more info in the docs starting from here: https://docs.spring.io/spring-integration/docs/current/reference/html/overview.html#configuration-enable-integration
I have the following scenario:
There will be a Java language testbed system consisting of a number of "services" that collaborate by passing messages to one another. The service implementation is intended to be generic, i.e. there is no specific "business logic" contained within. For the purposes of the testbed it is important to be able to create various collections of services, configured externally (if possible).
The services themselves are unaware of the existence of any other service. Each service simply subscribes to the topics where it expects to receive information and publishes on topics where it sends information out to any waiting subscribers. With careful configuration it then would be possible to simulate a data flow graph.
The plan is to configure a given service instance by providing configuration information that describes the information needed to set up subscribers (readers) and publishers (writers). The configuration information may include other properties not related to publish/subscribe.
Below is a possible example:
Note: XML was chosen for the example simply because it's easy enough to read and allows for structured data.
<service>
<name>Service A</name>
<service-id>service ID</service-id>
<publish>
<per-second>5</per-second>
<topic>
<name>Topic 1</name>
<class>org.xyz.Topic1</class>
<!-- override 5/sec rate -->
<per-second>10</per-second>
</topic>
<topic>
<name>Topic 2</name>
<class>org.xyz.Topic2</class>
</topic>
</publish>
<subscribe>
<topic>
<name>Topic 3</name>
<class>org.xyz.Topic3</class>
</topic>
</subscribe>
</service>
<service>
<name>Service B</name>
<service-id>service ID</service-id>
<publish>
<per-second>30</per-second>
<topic>
<name>Topic 3</name>
<class>org.xyz.Topic3</class>
</topic>
</publish>
<subscribe>
<topic>
<name>Topic 2</name>
<class>org.xyz.Topic2</class>
</topic>
</subscribe>
</service>
...
I would like to use the Spring framework to help with the configuration of these services. Note: I am very new to Spring and am currently reading Spring in Action (and other sources) to educate myself.
What I would like to know is: How could I "inject" the configuration information to some sort of controller or factory that would then use it to create the collection of services and provide them with the necessary information to create the readers and writers they will use to receive and send messages?
From what I've read so far, Spring appears to be pretty powerful WRT to dependency injection and "bean wiring", but I don't know enough about what can (and cannot) be done, nor how to do it.
I'm not partial to whether Spring is configured by Java or XML. I just used XML because it easy to put together, allows for data structuring and seems to be used everywhere. If it makes more sense to specify the configuration a different way, just let me know.
How a given service would handle an event (i.e. receive a specific message) to possibly send out a message "response", or take some other action, is a topic outside the scope of this question. I am researching how that could be done - mainly at rules based processing. If anyone has suggestions, I will gladly take a look at them.
Make a config file like this:
some.paremeter=cool
some.other.parameter=awesome
named myconfig.properties. Make sure the file is in your classpath, then include -Dspring.config.name=myconfig in your vm args; then in the xml you can use ${some.parameter} etc. In particular, putting the config file in <project-root>/config/ will work.
For example, here is a simple MongoClient from one of my projects that uses a spring config:
<!--Mongo-->
<bean id="mongoClient" class="com.mongodb.MongoClient">
<constructor-arg>
<bean class="com.mongodb.MongoClientURI">
<constructor-arg type="java.lang.String"
value="mongodb://${mongo.db.user}:${mongo.db.password}#${mongo.db.host}:${mongo.db.port}/${mongo.db.database}"/>
</bean>
</constructor-arg>
</bean>
I am using RabbitMQ with Spring Integration.
I want to register a message converter for a message listener like this:
<rabbit:listener-container
connection-factory="gesbRabbitmqConnectionFactory"
acknowledge="auto"
channel-transacted="true"
transaction-manager="rabbitTxManager"
task-executor="gesbSyncExecutor"
concurrency="1"
max-concurrency="2"
requeue-rejected="false"
message-converter="gesbDataMessageConverter">
<rabbit:listener
ref="gesbListenerBean"
queue-names="${gesb.partyid.queue}" />
</rabbit:listener-container>
When the application starts I've put a breakpoint in the setMessageConverter and my message converter gesbDataMessageConverter is set right.
But at runtime when the message arrives the message converter is the SimpleMessageConverter and not mine.
Any ideas?
As a workaround I've injected the converter in the listener and called once again the setMessageConverter and it seems to work but I do not know why initially it didn't. There is only one listener object and the set method is called only once.
The trick is with the combination of Spring AMQP and Spring Integration.
The AmqpInboundGateway has its own MessageConverter property and uses it from the raw MessageListener.
I mean that you should supply your custom gesbDataMessageConverter exactly into the <int-amqp:inbound-gateway> instead of the container.
I am trying to outhouse central beans of my OSGi bundles into a central bundle, which provides them as a service. This works fine with the ErrorHanlders and Processors, but not with the ShutdownStrategy and RedeliveryPolicy. The Error Message I receive is
org.osgi.service.blueprint.container.ComponentDefinitionException: A class org.apache.camel.processor.RedeliveryPolicy was found in the interfaces list, but class proxying is not allowed by default. The ext:proxy-method='classes' attribute needs to be added to this service reference.
I could try to follow the instrutction and add the ext:proxy-method, but first I want to understand the clue here. Maybe it's not a good idea to centralize strategies and policies?
[EDIT] The mistake here was to use the class in the service instead of an interface. So interface="org.apache.camel.spi.ShutdownStrategy" should be the correct Interface here (for the ShutdownStrategy). The bundle with my camel route references this service so:
<reference
id="shutdownStrategy"
interface="org.apache.camel.spi.ShutdownStrategy"
component-name="shutdownStrategy" />
But now I get the following error:
java.lang.IllegalArgumentException: CamelContext must be specified
[EDIT] I want to confine this question to the ShutdownStrategy, because the RedeliveryPolicy works fine when I referenc it in the ErrorHandlers inside my central bundle.
So is it possible to outhouse the ShutdownStrategy, too? Maybe not, because it needs a CamelContext.
When using Spring XML you then just define a spring bean which implements the org.apache.camel.spi.ShutdownStrategy and Camel will look it up at startup and use it instead of its default.
I found the answer in the Camel documentation
You can implement your own strategy to control the shutdown by implementing the org.apache.camel.spi.ShutdownStrategy and the set it on the CamelContext using the setShutdownStrategy method.
When using Spring XML you then just define a spring bean which implements the org.apache.camel.spi.ShutdownStrategy and Camel will look it up at startup and use it instead of its default.
So if you have your own implementation of the ShutdownStrategy you can use it as a bean.
<bean id="shutdownStrategy"
class="org.apache.camel.spi.ShutdownStrategy">
</bean>
I have the following XML configuration for a Kafka outbound channel adapter:
<int-kafka:outbound-channel-adapter id="kafkaOutboundChannelAdapter"
kafka-producer-context-ref="kafkaProducerContext"
auto-startup="true"
channel="activityOutputChannel">
<int:poller fixed-delay="1000" time-unit="MILLISECONDS" receive-timeout="0" task-executor="taskExecutor"/>
</int-kafka:outbound-channel-adapter>
<task:executor id="taskExecutor"
pool-size="5-25"
queue-capacity="20"
keep-alive="120"/>
This works just fine. I am trying to replicate this in the Java DSL, but I can't get too far. So far, I just have this:
.handle(Kafka.outboundChannelAdapter(kafkaConfig)
.addProducer(producerMetadata, brokerAddress)
.get());
I can't figure out how to add the taskExecutor and the poller with the DSL.
Any insight on how to incorporate these into my overall IntegrationFlow is appreciated.
The Spring Integration components (e.g. <int-kafka:outbound-channel-adapter>) consist with two beans: AbstractEndpoint to accept messages from the input-channel and MessageHandler to handle message.
So, Kafka.outboundChannelAdapter() is about MessageHandler. Any other endpoint-specific properties are up to the second Consumer<GenericEndpointSpec<H>> endpointConfigurer argument of .handle() EIP-method:
.handle(Kafka.outboundChannelAdapter(kafkaConfig)
.addProducer(producerMetadata, brokerAddress),
e -> e.id("kafkaOutboundChannelAdapter")
.poller(p -> p.fixedDelay(1000, TimeUnit.MILLISECONDS)
.receiveTimeout(0)
.taskExecutor(this.taskExecutor)));
See Reference Manual for more information.