MQTT- Spring Integration - spring-integration

I am trying to run the Sample MQTT-SPring integration project . How ever I have modified some the configuration details to fetch from property file . And trying connect to message broker from the runMQTT.java file.
Code snippet are as follow
MQTT-Context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:int-mqtt="http://www.springframework.org/schema/integration/mqtt"
xsi:schemaLocation="
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/integration/mqtt http://www.springframework.org/schema/integration/mqtt/spring-integration-mqtt-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<bean id="clientFactory"
class="org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory">
<property name="userName" value="username" />
<property name="password" value="password" />
<property name="serverURIs" value="${serveruri}"></property>
</bean>
<!-- intercept and log every message -->
<int:logging-channel-adapter id="logger"
level="ERROR" />
<int:wire-tap channel="logger" />
<!-- Mark the auto-startup="true" for starting MqttPahoMessageDrivenChannelAdapter from configuration -->
<int-mqtt:message-driven-channel-adapter
id="startCaseAdapter" client-id="clientId" url="${mqttbrokerurl}"
topics="topic" channel="startCase" auto-startup="true" />
<int:channel id="startCase" />
<int:service-activator id="startCaseService"
input-channel="startCase" ref="mqttCaseService" method="startCase" />
<bean id="mqttCaseService" class="com.XXX.integration.ieg.mqtt.MqttCaseService" />
</beans>
The properties(mqttbrokerurl, serveruri) are loaded from root context
RunMQTT
package com.XXX.integration.ieg.mqtt;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
public class RunMqtt {
public void test() throws MqttException{
ApplicationContext ac = new ClassPathXmlApplicationContext("/META-INF/spring/integration/mqtt/mqtt-context.xml");
System.out.println(ac);
MqttPahoMessageDrivenChannelAdapter startCaseAdapter = (MqttPahoMessageDrivenChannelAdapter)ac.getBean("startCaseAdapter");
//Uncomment to stop the adapter manually from program
//startCaseAdapter.start();
//DefaultMqttPahoClientFactory mqttClient = (DefaultMqttPahoClientFactory)ac.getBean("clientFactory");
DefaultMqttPahoClientFactory mqttClient = new DefaultMqttPahoClientFactory();
MqttClient mclient = mqttClient.getClientInstance("tcp://localhost:1883", "JavaSample");
String data = "This is what I am sending in 2nd attempt";
MqttMessage mm = new MqttMessage(data.getBytes());
mm.setQos(1);
mclient.connect();
mclient.publish("topic",mm);
mclient.disconnect();
//Uncomment to stop the adapter manually from program
//startCaseAdapter.stop();
}
public static void main(String[] args) throws MqttException {
new RunMqtt().test();
}
/*public static void main1(String[] args) {
String topic = "MQTT Examples";
String content = "Message from MqttPublishSample";
int qos = 2;
String broker = "tcp://localhost:1883";
String clientId = "JavaSample";
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
System.out.println("Connecting to broker: "+broker);
sampleClient.connect(connOpts);
System.out.println("Connected");
System.out.println("Publishing message: "+content);
MqttMessage message = new MqttMessage(content.getBytes());
message.setQos(qos);
sampleClient.publish(topic, message);
System.out.println("Message published");
sampleClient.disconnect();
System.out.println("Disconnected");
System.exit(0);
} catch(MqttException me) {
System.out.println("reason "+me.getReasonCode());
System.out.println("msg "+me.getMessage());
System.out.println("loc "+me.getLocalizedMessage());
System.out.println("cause "+me.getCause());
System.out.println("excep "+me);
me.printStackTrace();
}
}*/
}
The root context
The root context is as follow
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- This file will be the root context file for web app. All other context will be imported here -->
<!-- Security context . Now the spring security with basic authentication implemented. OAuth2 will be implemented -->
<import resource="security-config.xml" />
<!-- rest service call context -->
<import resource="classpath:META-INF/spring/integration/rest/applicationContext-http-int.xml"/>
<!-- Sftp context-->
<import resource="classpath:META-INF/spring/integration/sftp/SftpInboundReceive-context.xml"/>
<import resource="classpath:META-INF/spring/integration/sftp/SftpOutboundTransfer-context.xml"/>
<import resource="classpath:META-INF/spring/integration/sftp/SftpOutboundTransfer-poll.xml"/>
<!-- mqtt context-->
<import resource="classpath:META-INF/spring/integration/mqtt/mqtt-context.xml"/>
<!--Component scan base package -->
<context:component-scan base-package="com.XXX.integration.ieg"/>
<!-- All the property configuration moved to parent context file to solve the propert not found exception -->
<context:property-placeholder order="1"
location="classpath:/sftpuser.properties, classpath:/sftpfile.properties,classpath:/resthttp.properties, classpath:/mqtt.properties" ignore-unresolvable="true"/>
</beans>
In this case either mqtt or sftp or resthttp property loading is failing. Please help to resolve
stacktrace
java.lang.IllegalArgumentException: ${mqttbrokerurl}
at org.eclipse.paho.client.mqttv3.MqttConnectOptions.validateURI(MqttConnectOptions.java:448)
at org.eclipse.paho.client.mqttv3.MqttAsyncClient.<init>(MqttAsyncClient.java:260)
at org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory.getAsyncClientInstance(DefaultMqttPahoClientFactory.java:119)
at org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter.connectAndSubscribe(MqttPahoMessageDrivenChannelAdapter.java:189)
at org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter.doStart(MqttPahoMessageDrivenChannelAdapter.java:110)
at org.springframework.integration.endpoint.AbstractEndpoint.start(AbstractEndpoint.java:94)
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:173)
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:51)
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:346)
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:149)
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:112)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:770)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:483)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.XXX.integration.ieg.mqtt.RunMqtt.test(RunMqtt.java:18)
at com.XXX.integration.ieg.mqtt.RunMqtt.main(RunMqtt.java:39)
The properties file
mqtt.properties
mqttbrokerurl=tcp://172.18.128.150:1883

See this answer. When running in a web app, the classpath is relative to the web context.

According to StackTrace your property-placeholders aren't resolved and that's just because you don't have <context:property-placeholder> for your properties file.
Even if you say that it is:
The properties(mqttbrokerurl, serveruri) are loaded from root context
I don't see that stuff in your code:
You show only MQTT-Context.xml
Your RunMqtt starts only that context:
new ClassPathXmlApplicationContext("/META-INF/spring/integration/mqtt/mqtt-context.xml");
So, fix, please, those issues and come back to us with further progress.

Related

Reuse of service-activator for several gateway methods with Splitter

does somebody happen to know if it is valid to reuse a service activator and so also the output-channel using several methods (inbound) especially with a splitter and aggregator.
--> Always with result on the gateway.
In several tests it seems to work fine. As soon I added a splitter with an aggregator I get wrongs result routed to the gateway which then fails with a conversion exception (here in my case it cannot convert boolean to integer).
Thanks,
Paul
Flow
Spring Integration Config
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
<int:gateway service-interface="activity.BulbMessageGateway">
<int:method name="sendToBulb" request-channel="bulbMessages" reply-channel="bulbSendResult"></int:method>
<int:method name="updateHomeLightStatus" request-channel="homeBulbEntity" reply-channel="homeBulbEntityResult">
</int:method>
<int:method name="updateLightStatus" request-channel="bulbEntities" reply-channel="bulbSendResult">
<int:header name="homeId" expression="#args[0].homeId"/>
<int:header name="bulbId" expression="#args[0].strongId"/>
</int:method>
</int:gateway>
<int:channel id="bulbMessages" />
<int:channel id="bulbSendResult" />
<int:channel id="bulbEntities" />
<int:channel id="homeBulbEntity" />
<int:channel id="homeBulbEntityResult" />
<int:chain input-channel="homeBulbEntity" output-channel="bulbEntities">
<int:splitter expression="payload.bulbs" />
<int:header-enricher>
<int:header name="bulbId" expression="payload.strongId"/>
<int:header name="homeId" expression="payload.homeId"/>
</int:header-enricher>
</int:chain>
<int:transformer method="bulbToLightStatus" input-channel="bulbEntities" output-channel="bulbMessages">
<bean class="util.BulbTransformer"></bean>
</int:transformer>
<int:aggregator input-channel="bulbSendResult" output-channel="homeBulbEntityResult" method="aggregate">
<bean class="util.BooleanAggregator" />
</int:aggregator>
<int:service-activator input-channel="bulbMessages" output-channel="bulbSendResult" method="send">
<bean class="activity.BulbWebsocketMessageSenderBA" />
</int:service-activator>
</beans>
Unit test
#Test
public void sendMessageNoReceiver() {
assertFalse(gateway.sendToBulb(new HomeId("1"), new BulbId("1"), BulbMessageBuilder.restart("foo")));
}
#Test
public void sendMessageWithReceiver() {
MockSession<BulbId, BulbBE> bulbSession = new MockSession<BulbId, BulbBE>(new BulbBE(HomeId.of("1"), BulbId.of("1"), "bulb", "pass"));
registry.addBulbSession(bulbSession);
assertTrue(gateway.sendToBulb(new HomeId("1"), new BulbId("1"), BulbMessageBuilder.restart("foo")));
assertEquals(1, bulbSession.receivedMessages());
}
#Test
public void updateBulbStatus() {
final MockSession<BulbId, BulbBE> bulbSession1 = new MockSession<BulbId, BulbBE>(new BulbBE(HomeId.of("1"), BulbId.of("1"), "bulb", "pass"));
assertFalse(gateway.updateLightStatus(bulbSession1.getIdentity()));
registry.addBulbSession(bulbSession1);
assertTrue(gateway.updateLightStatus(bulbSession1.getIdentity()));
assertEquals(1, bulbSession1.receivedMessages());
final MockSession<BulbId, BulbBE> bulbSession2 = new MockSession<BulbId, BulbBE>(new BulbBE(HomeId.of("1"), BulbId.of("2"), "bulb", "pass"));
assertFalse(gateway.updateLightStatus(bulbSession2.getIdentity()));
registry.addBulbSession(bulbSession2);
assertTrue(gateway.updateLightStatus(bulbSession2.getIdentity()));
assertTrue(gateway.updateLightStatus(bulbSession2.getIdentity()));
assertEquals(2, bulbSession2.receivedMessages());
assertEquals(1, bulbSession1.receivedMessages());
}
#Test
public void updateHomeBulbStatus() {
final HomeBE home = new HomeBE();
home.setId(new ObjectId());
final MockSession<BulbId, BulbBE> bulbSession1 = new MockSession<BulbId, BulbBE>(new BulbBE(home.getStrongId(), BulbId.of("1"), "bulb", "pass"));
registry.addBulbSession(bulbSession1);
final MockSession<BulbId, BulbBE> bulbSession2 = new MockSession<BulbId, BulbBE>(new BulbBE(home.getStrongId(), BulbId.of("2"), "bulb", "pass"));
registry.addBulbSession(bulbSession2);
home.addBulb(bulbSession1.getIdentity());
assertEquals(1, gateway.updateHomeLightStatus(home));
assertEquals(1, bulbSession1.receivedMessages());
assertEquals(0, bulbSession2.receivedMessages());
home.addBulb(bulbSession2.getIdentity());
assertEquals(2, gateway.updateHomeLightStatus(home));
assertEquals(2, bulbSession1.receivedMessages());
assertEquals(1, bulbSession2.receivedMessages());
}
The last test fails if it is executed together with the other tests. It passes if it is executed alone.
The error is that the last method (using the splitter) receives now a boolean, which seems to be a result of the other two methods registered. The result of these methods is a boolean.
Please, share config on the matter.
And according your graph it would be better if you'd minimize the config as much as possible to isolate the problem.
From other side, please, be more specific: your question is fully unclear.
That is your own service. How can we be sure that it is safe to be used in different places? Only you, as an author, can determine that.
UPDATE
Sorry for the delay. Was busy with the release.
And thank for sharing the config for your use-case.
Now I see the problem.
You use everywhere on the gateway's methods a reply-channel. See the documentation on the matter when you need that:
Typically you don’t have to specify the default-reply-channel, since a Gateway will auto-create a temporary, anonymous reply channel, where it will listen for the reply. However, there are some cases which may prompt you to define a default-reply-channel (or reply-channel with adapter gateways such as HTTP, JMS, etc.).
Since you use the same bulbSendResult in different places the behavior is really unpredictable. Moreoever that channel is DirectChannel, so the round-robin balancer are on the scene.
You should get rid of those reply-channel's at all and just rely from your downstream components on the replyChannel header. Therefore you should remove those output-channels in the components which are intended to return replies to your gateway.
For example the last service-activator should be just like this:
<int:service-activator input-channel="bulbMessages" method="send">
<bean class="activity.BulbWebsocketMessageSenderBA"/>
</int:service-activator>
Since you general question how to reuse this service-activator, I'm answering to the question having the config from you:
<int:chain input-channel="homeBulbEntity">
<int:splitter expression="payload.bulbs"/>
<int:header-enricher>
<int:header name="bulbId" expression="payload.strongId"/>
<int:header name="homeId" expression="payload.homeId"/>
</int:header-enricher>
<int:transformer method="bulbToLightStatus">
<bean class="util.BulbTransformer"/>
</int:transformer>
<int:gateway request-channel="bulbMessages"/>
<int:aggregator method="aggregate">
<bean class="util.BooleanAggregator"/>
</int:aggregator>
</int:chain>
Pay attention to the absent output-channel for the <chain>. Therefore it sends reply directly to the replyChannel from headers and as a return to your updateHomeLightStatus gateway's method.
Another trick is that <int:gateway request-channel="bulbMessages"/> which sends messages in the middle of the <chain> flow to your <service-activator> and wait for the reply from there exactly the same way as a top-level gateway - via replyChannel header. For the <service-activator> without an output-channel it is a black-box where to send the reply. It uses just replyChannel from headers!
After receiving the reply gateway in the <chain> push the message to the <aggregator>.
When aggregator will do its logic, the result will be send to the top-level gateway as an output from the <chain>.
That's all.
Let me know what else isn't clear here.

not able see messages published from Kafka producer(Spring Integration)

Im using Spring Integration in Java Rest api to produce messages into Kafka..
https://github.com/spring-projects/spring-integration-kafka
when i say
kafkaMessageChannel.send(MessageBuilder.withPayload("hi kafka from rest api").build());
this returns true that means its publishing ..but not able to see the messages in the topic logs..
i checked the logs under /usr/local/var/lib/kafka-logs/test-0
even i ran the consumer console but im not able to see the messages published from api..
kafka-console-consumer.sh --zookeeper localhost:2181 --topic test --from-beginning
but if i produce messages from producer console im able to see messages in the topic logs as well as consumer console..
kafka-console-producer.sh --broker-list localhost:9092 --topic test
im using same brokerlist and topic name in spring integrated rest api..
my spring config outbound xml..
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-kafka="http://www.springframework.org/schema/integration/kafka"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/integration/kafka http://www.springframework.org/schema/integration/kafka/spring-integration-kafka.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<int:channel id="producerKafka">
<int:queue/>
</int:channel>
<int-kafka:outbound-channel-adapter
id="kafkaOutboundChannelAdapter"
kafka-producer-context-ref="kafkaProducerContext"
channel="producerKafka">
<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" keep-alive="120" queue-capacity="500"/>
<int-kafka:producer-context id="kafkaProducerContext">
<int-kafka:producer-configurations>
<int-kafka:producer-configuration broker-list="localhost:9092"
topic="test"
sync="true"
key-class-type="java.lang.String"
key-encoder="encoder"
value-class-type="java.lang.String"
value-encoder="encoder"
partitioner="partitioner"
compression-type="none"
producer-listener="kafkalistner"/>
</int-kafka:producer-configurations>
</int-kafka:producer-context>
<bean id="encoder"
class="org.springframework.integration.kafka.serializer.common.StringEncoder" />
<bean id="kafkalistner" class="kafka.producer.rest.model.ProducerListnerKafka" />
<bean id="partitioner" class="org.springframework.integration.kafka.support.DefaultPartitioner"/>
</beans>
And the listener implementation..
public class ProducerListnerKafka extends LoggingProducerListener{
#Override
public void setIncludeContents(boolean includeContents) {
super.setIncludeContents(true);
}
#Override
public void onError(String topic, Integer partition, Object key, Object payload, Exception exception) {
super.onError(topic, partition, key, payload, exception);
}
#Override
public void onSuccess(String topic, Integer partition, Object key, Object value, RecordMetadata recordMetadata) {
String kafkatopic=recordMetadata.topic();
}
}
i tried debugging its not even coming to onError function.

Spring Integration with ftp to perform operation using file

I want to read file from ftp and store it locally and after storing it locally i want to process that file in java code. After processing the file successfully i want to move it to another directory. How to do it efficiently with using spring integration with ftp
public class FtpFileHandler {
public File ftpFileUserHandler(#Header("timestamp") String timestamp, File file){
try {
String filename = file.getName();
String extension = FilenameUtils.getExtension(filename);
}
return file;
} catch ( IOException | org.json.simple.parser.ParseException e) {
Utility.exceptionLogger(e);
return file;
}
}
}
<bean id="ftpFileHandlerService" class="com.aaa.clear.integration.service.impl.FtpFileHandler" />
<!-- HR Integration Start -->
<int-ftp:inbound-channel-adapter id="ftpInbound"
session-factory="ftpSessionFactory"
charset="UTF-8"
auto-create-local-directory="true"
delete-remote-files="true"
filename-regex=".*\.(txt)$"
remote-directory="/FTP Test"
remote-file-separator="/"
preserve-timestamp="true"
temporary-file-suffix=".writing"
local-directory="#{systemProperties['aaa']}/clear/integration/download/user">
<int:poller fixed-rate="180000" />
</int-ftp:inbound-channel-adapter>
<int:service-activator id="" input-channel="ftpInbound" output-channel="ftpOutbound" ref="ftpFileHandlerService" method="ftpFileUserHandler" >
</int:service-activator>
<int-ftp:outbound-channel-adapter id="ftpOutbound" session-factory="ftpSessionFactory" auto-create-directory="true"
remote-directory="/FTP Test/processed/user"/>
Read the documentation
Check out the samples here and here
Come back if you have a specific question

Spring Integration - how to keep the orginal payload and use it later?

I would like to keep the original payload of the original requests and ise it in a xslt-transformer or in other operation. I lose it because I use an xslt-transformer and I need just some of the elements in the transformation. So my scenario is:
1.inbound-gateway (incoming WS req) -> 2.xslt-transformer (mapping for calling an external WS) -> 3.outbound-gateway (calling the external WS) -> 4.xslt-transformer (creating response from the resp. of the external WS and the original req)
At the 4th step I don't have the original req but I'd need it as I have to put values from it to the response. How could I implement it?
Thanks,
V.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration" xmlns:int-ws="http://www.springframework.org/schema/integration/ws" xmlns:int-xml="http://www.springframework.org/schema/integration/xml" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/integration/ws http://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/integration/xml http://www.springframework.org/schema/integration/xml/spring-integration-xml.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="authenticator" class="uk.co.virginmedia.test.Authenticator"/>
<bean id="webserviceDestinationProvider" class="uk.co.virginmedia.test.WebserviceDestinationProvider"/>
<bean id="resultToDocumentTransformer" class="org.springframework.integration.xml.transformer.ResultToDocumentTransformer"/>
<util:map id="orderNamespaceMap">
<entry key="res" value="http://schema/ReserveAppointment/2/0" />
</util:map>
<int-ws:inbound-gateway id="ws-gateway-for-rbta" request-channel="incoming-req-channel" reply-channel=""/>
<int:channel id="incoming-req-channel"/>
<int:service-activator id="authentication" input-channel="incoming-req-channel" ref="authenticator" method="authenticate" output-channel="authenticated-channel" />
<int:channel id="authenticated-channel"/>
<int-xml:xpath-router id="servicetype-router" input-channel="authenticated-channel" evaluate-as-string="true">
<int-xml:xpath-expression expression="//res:ReserveAppointmentRequest/res:serviceType/text()" ns-prefix="res" ns-uri="http://schema/ReserveAppointment/2/0"/>
<int-xml:mapping value="Broadband" channel="broadband-channel"/>
<int-xml:mapping value="FTTC+WholesaleLineRental" channel="fttc-wlr-channel"/>
</int-xml:xpath-router>
<int:channel id="broadband-channel"/>
<int-xml:xslt-transformer id="req_for_bt_xslt_transformer" input-channel="broadband-channel" output-channel="domresult_for_bt_channel" xsl-resource="classpath:/xsl/ToBTReq.xsl" result-type="StringResult"/>
<int:channel id="domresult_for_bt_channel"/>
<int:transformer input-channel="domresult_for_bt_channel" output-channel="document_for_bt_channel" expression="payload.toString()"/>
<int:channel id="document_for_bt_channel"/>
<int-ws:outbound-gateway request-channel="document_for_bt_channel" reply-channel="resp_from_bt_channel" destination-provider="webserviceDestinationProvider" id="call_bt-outbound_gateway" />
<int:channel id="resp_from_bt_channel"/>
<int-xml:xslt-transformer id="resp_for_rbta_xslt_transformer" input-channel="resp_from_bt_channel" output-channel="resp_for_rbta_channel" xsl-resource="classpath:/xsl/ToBTReq.xsl" result-type="StringResult"/>
Since your original message is just text you could copy it to a header field. This should work as long as you don't do anything special in between when you store and afterwards retrieve it.
So what I would try is:
<int:header-enricher input-channel="authenticated-channel" output-channel="pre-routing-channel">
<int:header name="original-payload" expression="payload.toString()" />
</int:header-enricher>
<!-- changed input channel of router -->
<int-xml:xpath-router id="servicetype-router" input-channel="pre-routing-channel" evaluate-as-string="true">
If this is not working for you (maybe because you have to do something more special in between or the payload is too big), you still have the option to use a ClaimCheck. Which is actually exactly what you are asking for. For this you'll need a MessageStore and then just store the message payload before modifying it. So instead of the header-enricher you will call
<int:claim-check-in input-channel="authenticated-channel" output-channel="pre-routing-channel" message-store="payloadstore" />
<!-- MessageStore definition storing payload using in memory map -->
<bean id="simpleMessageStore"
class="org.springframework.integration.store.SimpleMessageStore"/>

How to use Nhibernate Validator + NHib component + ddl

I just configured my NHibValidator. My NHibernate creates the DB
schema. When I set MaxLenght="20" to some property of a class then in
the database the length appears in the database column. I am doing
this in the NHibValidator xml file. But the problem is that I have
components and cannot figure out how to achieve this behaviour. The
component is configured correctly in the Customer.hbm.xml file.
EDIT:
Well, I found that Hibernate Validator users had the same problem two
years ago.
http://opensource.atlassian.com/projects/hibernate/browse/HV-25
Is this an issue for NHibernate Validator or it is fixed. If it is
working tell me how please.
-----------------------------------------------------
public class Customer
{
public virtual string Name{get;set;}
public virtual Contact Contacts{ get; }
}
-----------------------------------------------------
public class Contact
{
public virtual string Address{get;set;}
}
-----------------------------------------------------
<?xml version="1.0" encoding="utf-8" ?>
<nhv-mapping xmlns="urn:nhibernate-validator-1.0"
namespace="MyNamespace"
assembly="MyAssembly">
<class name="Customer">
<property name="Name">
<length max="20"/>
</property>
<property name="Contacts">
<notNull/>
<valid/>
</property>
</class>
</nhv-mapping>
-----------------------------------------------------
<?xml version="1.0" encoding="utf-8" ?>
<nhv-mapping xmlns="urn:nhibernate-validator-1.0"
namespace="MyNamespace"
assembly="MyAssembly">
<class name="Contact">
<property name="Address">
<length max="50"/>
<valid/>
</property>
</class>
</nhv-mapping>
-----------------------------------------------------
Well, this should be a bug. I posted this to NHibernate issue tracker.
https://nhibernate.jira.com/browse/NHV-82
UPDATE: the issue is solved.

Resources