I'm new in Spring Integration and i've been triyng some examples on the net, and I found that very helpful repo on github :
spring-integration-samples
For a better anderstanding I tried combinig some example, but then got stuck, my goal was to use the example of ws-inbound-gateway with the file example in order to create a file with the WS request text using the file outbound-gateway and then send back the response of the WS.
For that I did the folowing modifications to the inbound-gateway-config.xml of the ws-inbound-gateway example:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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-file="http://www.springframework.org/schema/integration/file"
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/file
http://www.springframework.org/schema/integration/file/spring-integration-file.xsd">
<int:channel id="input"/>
<int-ws:inbound-gateway id="ws-inbound-gateway" request-channel="input"/>
<int-file:outbound-gateway id="mover" request-channel="input"
reply-channel="output"
directory="file:${java.io.tmpdir}/spring-integration-samples/output" />
<int:channel id="output"/>
<int:service-activator input-channel="output">
<bean class="org.springframework.integration.samples.ws.SimpleEchoResponder"/>
</int:service-activator>
</beans>
The rest still the same.
Unfortunally i get bthe following Exception when i try to send a request to the WS:
org.springframework.ws.client.WebServiceTransportException: Erreur Interne de Servlet [500]
at org.springframework.ws.client.core.WebServiceTemplate.handleError(WebServiceTemplate.java:695)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:606)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:506)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:446)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:429)
at org.springframework.integration.samples.ws.InContainerTests.testWebServiceRequestAndResponse(InContainerTests.java:52)
and then when i tried entring the link in my browser i got:
cause mère
org.xml.sax.SAXParseException; lineNumber: 20; columnNumber: 75; cvc-complex-type.2.4.c : Le caractère générique concordant est strict, mais aucune déclaration ne peut être trouvée pour l'élément 'int-file:outbound-gateway'.
com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437)
com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368)
com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325)
...
I don't know if I'm missing a declaration in my web.xml or am I getting the chanelling wrong.
Thanks in advence ^^
Using a transformer to transform the DOM message to a String message and the send it to a service activator. like so:
<int-ws:inbound-gateway id="ws-inbound-gateway" request-channel="input"/>
<int:channel id="input"/>
<int:transformer input-channel="input" output-channel="transform" >
<bean class="org.springframework.integration.samples.ws.SimpleTransformerResponder"/>
</int:transformer>
<int:channel id="transform"/>
<int:service-activator input-channel="transform" output-channel="next">
<bean class="org.springframework.integration.file.FileWritingMessageHandler" >
<constructor-arg name="destinationDirectory" value="file:${java.io.tmpdir}/"/>
</bean>
</int:service-activator>
<int:channel id="next"/>
<int:service-activator input-channel="next">
<bean class="org.springframework.integration.samples.ws.SimpleEchoResponder" />
</int:service-activator>
the transformer bean:
public class SimpleTransformerResponder {
public String transform(DOMSource request) {
return request.getNode().getTextContent();
}
}
and the response bean
public class SimpleEchoResponder {
public Source issueResponseFor(File request) {
return new DomSourceFactory().createSource(
"<echoResponse xmlns=\"http://www.springframework.org/spring-ws/samples/echo\">" +
request.getAbsoluteFile() + "</echoResponse>");
}
}
the result is a file with the content of the initial message created, and the response contains the path of the file created.
"Learning hard ^^ "
Related
I have a Spring Integration flow that reads a csv file from a directory, splits the lines, then processes each line and extracts 2 objects from each line. These two objects are then send to two seperate int-mongodb:outbound-channel-adapter. I want to delete the incoming file after all of the lines have been processed and persisted. I have seen example of using the Transaction Manager to do this with the inbound adapter, but nothing with the outbound adapter. Is there a way to do this?
My config looks something like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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
http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
http://www.springframework.org/schema/integration/mongodb http://www.springframework.org/schema/integration/mongodb/spring-integration-mongodb.xsd
http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-file="http://www.springframework.org/schema/integration/file"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:int-mongodb="http://www.springframework.org/schema/integration/mongodb"
xmlns:mongo="http://www.springframework.org/schema/data/mongo">
<int:poller default="true" fixed-delay="50"/>
<int-file:inbound-channel-adapter id="filesInChannel"
directory="file:${file.ingest.directory}"
auto-create-directory="true">
<int:poller id="poller" fixed-rate="100">
</int:poller>
</int-file:inbound-channel-adapter>
<task:executor id="executor" pool-size="10" queue-capacity="50" />
<int:channel id="executorChannel">
<int:queue capacity="50"/>
</int:channel>
<int:splitter input-channel="filesInChannel" output-channel="executorChannel"
expression="T(org.apache.commons.io.FileUtils).lineIterator(payload)"/>
<int:service-activator id="lineParserActivator" ref="lineParser" method="parseLine"
input-channel="executorChannel" output-channel="lineChannel">
<int:poller task-executor="executor" fixed-delay="500">
</int:poller>
</int:service-activator>
<bean name="lineParser" class="com.xxx.LineParser"/>
<int:channel id="lineChannel">
<int:queue/>
</int:channel>
<int:channel id="lineMongoOutput">
<int:queue/>
</int:channel>
<int:channel id="actionMongoOutput">
<int:queue/>
</int:channel>
<int:transformer input-channel="lineChannel" output-channel="lineMongoOutput">
<bean id="lineTransformer" class="com.xxx.transformer.LineTransformer"></bean>
</int:transformer>
<int:transformer input-channel="lineChannel" output-channel="actionMongoOutput">
<bean id="actionTransformer" class="com.xxx.transformer.ActionTransformer"></bean>
</int:transformer>
<mongo:db-factory id="mongoDbFactory" dbname="${mongo.db.name}" password="${mongo.db.pass}" username="${mongo.db.user}" port="${mongo.db.port}" host="${mongo.db.host}"/>
<int-mongodb:outbound-channel-adapter id="lineMongoOutput"
collection-name="full"
mongodb-factory="mongoDbFactory" />
<int-mongodb:outbound-channel-adapter id="actionMongoOutput"
collection-name="action"
mongodb-factory="mongoDbFactory" />
</beans>
You can't really do it on the outbound adapter because you don't know when you're "done". Given you are asynchronously handing off to the downstream flow (via executors and queue channels), you can't do it on the inbound adapter either, because the poller thread will return to the adapter as soon as all the splits are sent.
Aside from that, I see some issues in your flow:
You seem to have an excessive amount of thread handoffs - you really don't need queue channels in the downstream flow because your executions are controlled by the exec. channel.
It is quite unusual to make every channel a QueueChannel.
Finally, you have 2 transformers subscribed to the same channel.
Do you realize that messages sent to lineChannel will alternate round-robin style.
Perhaps that is your intent, given your description, but it seems a little brittle to me; I would prefer to see the different data types going to different channels.
If you avoid using queue channels, and use gateways within your service activator to send out the data to the mongo adapters, your service activator would know when it is complete and be able to remove the file at that time.
EDIT:
Here is one solution (it writes to logs rather than mongo, but you should get the idea)...
<int-file:inbound-channel-adapter directory="/tmp/foo" channel="toSplitter">
<int:poller fixed-delay="1000">
<int:transactional synchronization-factory="sf" transaction-manager="ptxMgr" />
</int:poller>
</int-file:inbound-channel-adapter>
<int:transaction-synchronization-factory id="sf">
<int:after-commit expression="payload.delete()" />
<int:after-rollback expression="payload.renameTo(new java.io.File('/tmp/bad/' + payload.name))" />
</int:transaction-synchronization-factory>
<bean id="ptxMgr" class="org.springframework.integration.transaction.PseudoTransactionManager" />
<int:splitter input-channel="toSplitter" output-channel="processChannel">
<bean class="org.springframework.integration.file.splitter.FileSplitter" />
</int:splitter>
<int:service-activator input-channel="processChannel">
<bean class="foo.Foo">
<constructor-arg ref="gate" />
</bean>
</int:service-activator>
<int:gateway id="gate" service-interface="foo.Foo$Gate">
<int:method name="toLine" request-channel="toLine" />
<int:method name="toAction" request-channel="toAction" />
</int:gateway>
<int:channel id="toLine" />
<int:logging-channel-adapter channel="toLine" expression="'LINE:' + payload" level="WARN"/>
<int:channel id="toAction" />
<int:logging-channel-adapter channel="toAction" expression="'ACTION:' + payload" level="WARN"/>
.
public class Foo {
private final Gate gateway;
public Foo(Gate gateway) {
this.gateway = gateway;
}
public void parse(String payload) {
String[] split = payload.split(",");
if (split.length != 2) {
throw new RuntimeException("Bad row size: " + split.length);
}
this.gateway.toLine(split[0]);
this.gateway.toAction(split[1]);
}
public interface Gate {
void toLine(String line);
void toAction(String action);
}
}
.
#ContextConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
public class FooTests {
#Test
public void testGood() throws Exception {
File file = new File("/tmp/foo/x.txt");
FileOutputStream fos = new FileOutputStream(file);
fos.write("foo,bar".getBytes());
fos.close();
int n = 0;
while(n++ < 100 && file.exists()) {
Thread.sleep(100);
}
assertFalse(file.exists());
}
#Test
public void testBad() throws Exception {
File file = new File("/tmp/foo/y.txt");
FileOutputStream fos = new FileOutputStream(file);
fos.write("foo".getBytes());
fos.close();
int n = 0;
while(n++ < 100 && file.exists()) {
Thread.sleep(100);
}
assertFalse(file.exists());
file = new File("/tmp/bad/y.txt");
assertTrue(file.exists());
file.delete();
}
}
Add a task executor to the <poller/> to process multiple files concurrently. Add a router as needed.
This is my context 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-amqp="http://www.springframework.org/schema/integration/amqp"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/integration/amqp http://www.springframework.org/schema/integration/amqp/spring-integration-amqp.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
<rabbit:connection-factory id="connectionFactory" host="localhost"/>
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"/>
<rabbit:queue name="upload-queue"/>
<rabbit:admin connection-factory="connectionFactory"/>
<rabbit:topic-exchange name="infrastructure-exchange">
<rabbit:bindings>
<rabbit:binding queue="upload-queue" pattern="ru.interosite.*"/>
</rabbit:bindings>
</rabbit:topic-exchange>
<int-amqp:outbound-channel-adapter
channel="toRabbit"
routing-key="ru.interosite.1"
amqp-template="amqpTemplate"
exchange-name="infrastructure-exchange"/>
<int-amqp:inbound-channel-adapter
channel="fromRabbit"
queue-names="upload-queue"
connection-factory="connectionFactory"
/>
<int:gateway id="infrastructureGateway" service-interface="com.dropbyke.web.api.service.InfrastructureGateway"/>
<int:channel id="toRabbit"/>
<int:channel id="fromRabbit"/>
<bean id="testInfrastructureServiceImpl" class="com.dropbyke.web.api.service.TestInfrastructureServiceImpl"/>
<int:service-activator input-channel="fromRabbit" ref="testInfrastructureServiceImpl" method="handleToken" />
<!-- A Spring Integration adapter that routes messages sent to the helloWorldChannel to the bean named "helloServiceImpl"'s hello() method -->
<!--<int:outbound-channel-adapter channel="fromRabbit" ref="testInfrastructureServiceImpl" method="handleToken"/>-->
</beans>
This is gateway interface:
public interface InfrastructureGateway {
#Gateway(requestChannel = "toRabbit")
void doUpload(UserTokenDTO tokenDTO);
}
Message endpoint that supposed to handle calls:
#MessageEndpoint
public class TestInfrastructureServiceImpl implements TestInfrastructureService {
public void handleToken( UserTokenDTO tokenDTO) {
System.out.println("Handle user token " + tokenDTO.getToken());
}
}
So when I invoke gateway's doUpload method I'm getting this error message:
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1004E:(pos 8): Method call: Method handleToken(byte[]) cannot be found on com.dropbyke.web.api.service.TestInfrastructureServiceImpl type
If I exclude Rabbit part then all works fine. What should I do to make it work with Rabbit? Should I implement some converter from byte[] to my domain object UserTokenDTO?
As nicolas-labrot suggested I had to make my UserTokenDTO to be a Serializable. After that all works fine.
Trying to run the sample spring-integration mqtt project from web.
I have imported the mqtt-context in root context. After the war is deployed I am running the RunMqtt.java file. But getting the following issue. If running in standalone mode , the same file does not give any issue.
Stack Trace
Creating instance of bean 'startCaseAdapter'
16:50:54.147 DEBUG [main][org.springframework.beans.BeanUtils] No property editor [org.springframework.integration.mqtt.core.MqttPahoClientFactoryEditor] found for type org.springframework.integration.mqtt.core.MqttPahoClientFactory according to 'Editor' suffix convention
16:50:54.148 TRACE [main][org.springframework.beans.TypeConverterDelegate] Field [topic] isn't an enum value
java.lang.NoSuchFieldException: topic
at java.lang.Class.getField(Class.java:1579)
at org.springframework.beans.TypeConverterDelegate.attemptToConvertStringToEnum(TypeConverterDelegate.java:336)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:257)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:107)
at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:64)
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:47)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:706)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1133)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1036)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:505)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:725)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
at com.iux.ieg.test.mqtt.RunMqtt.test(RunMqtt.java:24)
at com.iux.ieg.test.mqtt.RunMqtt.main(RunMqtt.java:46)
16:50:54.150 TRACE [main][org.springframework.beans.factory.support.DefaultListableBeanFactory] Ignoring constructor [public org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter(java.lang.String,java.lang.String,org.springframework.integration.mqtt.core.MqttPahoClientFactory,java.lang.String[])] of bean 'startCaseAdapter': org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'startCaseAdapter': Unsatisfied dependency expressed through constructor argument with index 2 of type [org.springframework.integration.mqtt.core.MqttPahoClientFactory]: Could not convert constructor argument value of type [java.lang.String] to required type [org.springframework.integration.mqtt.core.MqttPahoClientFactory]: Failed to convert value of type 'java.lang.String' to required type 'org.springframework.integration.mqtt.core.MqttPahoClientFactory'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [org.springframework.integration.mqtt.core.MqttPahoClientFactory]: no matching editors or conversion strategy found
16:50:54.150 TRACE [main][org.springframework.beans.TypeConverterDelegate] Converting String to [class [Ljava.lang.String;] using property editor [org.springframework.beans.propertyeditors.StringArrayPropertyEditor#821075]
16:50:54.150 TRACE [main][org.springframework.beans.TypeConverterDelegate] Field [clientId] isn't an enum value
java.lang.NoSuchFieldException: clientId
at java.lang.Class.getField(Class.java:1579)
at org.springframework.beans.TypeConverterDelegate.attemptToConvertStringToEnum(TypeConverterDelegate.java:336)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:257)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:107)
at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:64)
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:47)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:706)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1133)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1036)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:505)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:725)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
at com.iux.ieg.test.mqtt.RunMqtt.test(RunMqtt.java:24)
at com.iux.ieg.test.mqtt.RunMqtt.main(RunMqtt.java:46)
Configuration
Web-application-config.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: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-poll.xml" />
<!-- mqtt context -->
<import resource="classpath:META-INF/spring/integration/mqtt/mqtt-context.xml" />
<!-- Mail Context -->
<import
resource="classpath:META-INF/spring/integration/mail/mail-imap-idle-config.xml" />
<import
resource="classpath:META-INF/spring/integration/mail/mail-pop3-config.xml" />
<!--Component scan base package -->
<context:component-scan base-package="com.iux.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" ignore-unresolvable="true"/> -->
<context:property-placeholder order="0"
location="classpath:/sftpfile.properties" ignore-unresolvable="true" />
<context:property-placeholder order="1"
location="classpath:/sftpuser.properties" ignore-unresolvable="true" />
<context:property-placeholder order="2"
location="classpath:/resthttp.properties" ignore-unresolvable="true" />
<context:property-placeholder order="3"
location="classpath:/mqtt.properties" ignore-unresolvable="true" />
<context:property-placeholder order="4"
location="classpath:/mail.properties" />
</beans>
mqtt-context.xml
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">
<context:property-placeholder
location="classpath:/mqtt.properties" ignore-unresolvable="true" />
<!-- 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="${mqtt.brokerurl}"
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.iux.ieg.mqtt.MqttCaseService" />
MqttCaseService.java
import org.apache.log4j.Logger;
public class MqttCaseService {
private static Logger logger = Logger.getLogger(MqttCaseService.class);
public void startCase(String message){
logger.debug(message);
}
}
RunMqtt.java
public class RunMqtt {
private static Logger logger = Logger.getLogger(RunMqtt.class);
//#Test
public void test() throws MqttException{
ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext("/META-INF/spring/integration/mqtt/mqtt-context.xml");
logger.debug(context);
//MqttPahoMessageDrivenChannelAdapter startCaseAdapter = (MqttPahoMessageDrivenChannelAdapter)context.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://*messagebrokerurl*: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) {
try {
new RunMqtt().test();
} catch (MqttException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
the sample spring-integration mqtt project
Which sample?
Please show your configuration.
EDIT:
It looks like Spring is having trouble determining which constructor to use.
Try adding
<bean id="clientFactory" class="org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory" />
and add client-factory="clientFactory" to the message-driven adapter.
currently I am working with mule and need to write in WMQ Queue. But instead of using WMQ endpoint, I want to do it by using JMS Endpoint. Here is my configuration:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:jms="http://www.mulesoft.org/schema/mule/jms" xmlns:jetty="http://www.mulesoft.org/schema/mule/jetty" xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:wmq="http://www.mulesoft.org/schema/mule/ee/wmq" xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:data-mapper="http://www.mulesoft.org/schema/mule/ee/data-mapper" xmlns:ajax="http://www.mulesoft.org/schema/mule/ajax" xmlns:jersey="http://www.mulesoft.org/schema/mule/jersey" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.4.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/jersey http://www.mulesoft.org/schema/mule/jersey/current/mule-jersey.xsd
http://www.mulesoft.org/schema/mule/ajax http://www.mulesoft.org/schema/mule/ajax/current/mule-ajax.xsd
http://www.mulesoft.org/schema/mule/ee/data-mapper http://www.mulesoft.org/schema/mule/ee/data-mapper/current/mule-data-mapper.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
http://www.mulesoft.org/schema/mule/ee/wmq http://www.mulesoft.org/schema/mule/ee/wmq/current/mule-wmq-ee.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
http://www.mulesoft.org/schema/mule/jetty http://www.mulesoft.org/schema/mule/jetty/current/mule-jetty.xsd
http://www.mulesoft.org/schema/mule/jms http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd">
<wmq:connector name="WMQ" hostName="localhost" port="1414" queueManager="localmanager" validateConnections="true" doc:name="WMQ" ccsId="819"/>
<data-mapper:config name="map_to_xml" transformationGraphPath="map_to_xml.grf" doc:name="map_to_xml"/>
<data-mapper:config name="xml_to_json" transformationGraphPath="xml_to_json.grf" doc:name="xml_to_json"/>
<jms:connector name="jmsConnector"
connectionFactoryJndiName="jms/ConnectionFactory"
jndiInitialFactory="com.ibm.websphere.naming.WsnInitialContextFactory"
specification="1.1"
connectionFactory-ref="MQConnectionFactory">
<spring:property name="jmsSupport" ref="customJmsSupport"/>
</jms:connector>
<spring:beans>
<spring:bean id="customJmsSupport" class="CustomJms11Support">
<spring:constructor-arg ref="jmsConnector" />
</spring:bean>
<spring:bean name="MQConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<spring:property name="hostName" value="localhost"/>
<spring:property name="port" value="1414"/>
<spring:property name="queueManager" value="localmanager"/>
<spring:property name="transportType" value="1"/>
</spring:bean>
</spring:beans>
<flow name="RequestFlow" doc:name="RequestFlow">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8088" path="uebermittleAusweisdaten" doc:name="HTTP" contentType="text/html"/>
<expression-filter expression="#[message.payload !='/favicon.ico']" doc:name="Expression"/>
<jersey:resources doc:name="REST">
<component class="de.fraport.sources.RestClass"/>
</jersey:resources>
<set-variable variableName="id" value="#[message.id]" doc:name="Message ID"/>
<json:json-to-object-transformer returnClass="java.util.Map" doc:name="JSON to Object"/>
<data-mapper:transform config-ref="map_to_xml" doc:name="Map To XML">
<data-mapper:input-arguments>
<data-mapper:input-argument key="id">#[flowVars['id']]</data-mapper:input-argument>
</data-mapper:input-arguments>
</data-mapper:transform>
<flow-ref name="Subflow1" doc:name="Flow Reference"/>
<parse-template location="D:\Workspace\ajax_rest\src\main\app\www\index.html" doc:name="Parse Template"/>
</flow>
<sub-flow name="Subflow1" doc:name="Subflow1">
<mulexml:xslt-transformer encoding="ISO8859-1" maxIdleTransformers="2" maxActiveTransformers="5" xsl-file="D:\Workspace\ajax_rest\mobako.sender.xsl" doc:name="SOAP Envelope"/>
<mulexml:dom-to-xml-transformer outputEncoding="ISO8859-1" doc:name="DOM to XML"/>
<outbound-endpoint doc:name="JMS" address="jms://LSMH.ZKSEAP.SERVICEBUS" connector-ref="jmsConnector" encoding="ISO8859-1"/>
<!-- <wmq:outbound-endpoint queue="LSMH.ZKSEAP.SERVICEBUS" encoding="ISO8859-1" connector-ref="WMQ" doc:name="ZKSEAP IN"/> -->
<set-property propertyName="MULE_CORRELATION_ID" value="#[function:dateStamp:yyyy-MM-dd HH:mm:ss]" doc:name="Set Correlation ID"/>
<request-reply>
<vm:outbound-endpoint path="sender">
<message-properties-transformer scope="outbound">
<delete-message-property key="MULE_REPLYTO"/>
</message-properties-transformer>
</vm:outbound-endpoint>
<vm:inbound-endpoint path="response">
<logger level="INFO" message="#[string:XXXXXX 1: #[message.inboundProperties]"/>
</vm:inbound-endpoint>
</request-reply>
</sub-flow>
<flow name="ResponseFlow" doc:name="ResponseFlow">
<inbound-endpoint address="jms://ZKSEAP.LSMH.SERVICEBUS" connector-ref="jmsConnector" doc:name="ZKSEAP OUT"/>
<!-- <wmq:inbound-endpoint queue="ZKSEAP.LSMH.SERVICEBUS" connector-ref="WMQ" doc:name="ZKSEAP OUT" encoding="UTF-8"/> -->
<set-property propertyName="MULE_CORRELATION_ID" value="#[function:dateStamp:yyyy-MM-dd HH:mm:ss]" doc:name="Set Correlation ID"/>
<data-mapper:transform doc:name="XML To JSON" config-ref="xml_to_json"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<vm:outbound-endpoint path="response" doc:name="Response Outbound" exchange-pattern="one-way"/>
</flow>
</mule>
I have successfully read message from WMQ Queue by using JMS endpoint. However, when I tried to write some message in WMQ Queue by using JMS Endpoint, I got following error from my server:
2014-07-22 10:11:27,064 [Axis2 Task] ERROR WMQMsg - Expected MQ
message format ' MQSTR ', but received 'MQHRF2 ' 2014-07-22
10:11:27,064 [Axis2 Task] WARN QMgrConnection - Moving msg into dead
letter queue after 1 try/tries:
414D51206C6F63616C6D616E616765721A0CCE5320003C0 2 [Fatal Error] :1:1:
Content ist nicht zulõssig in Prolog. ERROR: 'Content ist nicht
zulõssig in Prolog.' 2014-07-22 10:11:27,064 [Axis2 Task] WARN ESBMsg
- Error prettifying ESBMsg for log printing
I know that this error occured because I tried to write into Non-JMS Queue. Also I know that I have to solve it by setting "?targetClient=1". However, when I tried to add the targetClient attribute into my Queue URL, I still got the error (it seems that the attribute was recognized as URL too by WMQ).
Then, from my research, I found out that I can not directly set the "?targetClient" in the url. Instead of that, I need to create a Java Class to set the "?targetClient". To create those class, I follow some instructions from following URL
Create Custom JMSSupport Class
But unfortunatelly, it also did not work for me. Anyone has an idea about how can I solve it? Thanks.
NB: In Apache Camel, I can simply solve it by adding:
<setHeader headerName="CamelJmsDestinationName">
<constant>queue:///LSMH.ZKSEAP.SERVICEBUS?targetClient=1</constant>
</setHeader>
Is there something similar in Mule ESB?
Just solved the problem:
It is right that we need to create a java class to set the targetClient. And to do so, we can follow the link that I gave above. However, we will need to change the code a bit.
Here is the right code:
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Session;
import org.mule.api.endpoint.ImmutableEndpoint;
import org.mule.transport.jms.Jms11Support;
import org.mule.transport.jms.JmsConnector;
import com.ibm.mq.jms.JMSC;
import com.ibm.mq.jms.MQQueue;
/**
* Implements WebSphere MQ specific JMS support for Mule. The class
* overrides the createDestination method to intercept JMS Queue object
* creation and sets the targetClient=1 property on created MQQueue
* objects. This is necessary to prevent non-JMS consumers from being
* choked by RFH2 headers.
*/
public class CustomJms11Support extends Jms11Support {
public CustomJms11Support(JmsConnector connector) {
super(connector);
}
#Override
public Destination createDestination(Session session, String name, boolean
topic, ImmutableEndpoint ie) throws JMSException {
Destination destination = super.createDestination(session, name, topic, ie);
if (destination instanceof MQQueue){
((MQQueue) destination).setTargetClient(JMSC.MQJMS_CLIENT_NONJMS_MQ);
}
return destination;
}
}
And then, we will need to set a property called "JMS_IBM_Character_Set" (If not we will get "Expected MQ message characterSet '819', but received '1208'" error) before send the request to JMS endpoint. Here is how I configure it:
<set-property propertyName="JMS_IBM_Character_Set" value="ISO8859_1" doc:name="Property"/>
And just for your information, by changing the WMQ endpoint to JMS endpoint, for sure it improve the performance.
Hopefully it would be useful :D
I'm trying to use spring integration email mechanism.
I used this link for reference:
http://blog.solidcraft.eu/2011/04/read-emails-from-imap-with-spring.html
unfortunately i get an error message on server start-up:
Caused by: java.lang.IllegalArgumentException: Target object of type [class src.com.project.myEmailReciever] has no eligible methods for handling Messages.
at org.springframework.util.Assert.notEmpty(Assert.java:294)
at org.springframework.integration.util.MessagingMethodInvokerHelper.findHandlerMethodsForTarget(MessagingMethodInvokerHelper.java:348)
at org.springframework.integration.util.MessagingMethodInvokerHelper.<init>(MessagingMethodInvokerHelper.java:165)
at org.springframework.integration.util.MessagingMethodInvokerHelper.<init>(MessagingMethodInvokerHelper.java:103)
at org.springframework.integration.util.MessagingMethodInvokerHelper.<init>(MessagingMethodInvokerHelper.java:107)
at org.springframework.integration.handler.MethodInvokingMessageProcessor.<init>(MethodInvokingMessageProcessor.java:48)
at org.springframework.integration.handler.ServiceActivatingHandler.<init>(ServiceActivatingHandler.java:42)
at org.springframework.integration.config.ServiceActivatorFactoryBean.createMethodInvokingHandler(ServiceActivatorFactoryBean.java:48)
at org.springframework.integration.config.AbstractStandardMessageHandlerFactoryBean.createHandler(AbstractStandardMessageHandlerFactoryBean.java:72)
at org.springframework.integration.config.AbstractSimpleMessageHandlerFactoryBean.createHandlerInternal(AbstractSimpleMessageHandlerFactoryBean.java:89)
at org.springframework.integration.config.AbstractSimpleMessageHandlerFactoryBean.getObject(AbstractSimpleMessageHandlerFactoryBean.java:68)
at org.springframework.integration.config.AbstractSimpleMessageHandlerFactoryBean.getObject(AbstractSimpleMessageHandlerFactoryBean.java:31)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142)
... 30 more
apparently the function in my receiving class :
public void receive(MimeMessage mimeMessage) {
//doSomthing
}
is not eligible for handling emails.. anyone know how do i solve this?
edit here are my classes\ xml's:
#Component
#Scope("prototype")
public class MessageFactory {
#Autowired
private ApplicationContext ctx;
private static final Logger logger = LoggerFactory.getLogger(MessageFactory.class);
ObjectMapper mapper = new ObjectMapper();
public boolean receive(MimeMessage mimeMessage) {
System.out.println("try");
return true;
}
}
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:mail="http://www.springframework.org/schema/integration/mail"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/integration/mail
http://www.springframework.org/schema/integration/mail/spring-integration-mail-2.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">
<util:properties id="javaMailProperties">
<prop key="mail.imap.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
<prop key="mail.imap.socketFactory.fallback">false</prop>
<prop key="mail.store.protocol">imaps</prop>
<prop key="mail.debug">true</prop>
</util:properties>
<mail:inbound-channel-adapter id="imapAdapter"
store-uri="imaps://username:password#imap.googlemail.com:993/INBOX"
channel="recieveEmailChannel"
should-delete-messages="false"
should-mark-messages-as-read="true"
auto-startup="true"
java-mail-properties="javaMailProperties">
<int:poller fixed-delay="5" time-unit="SECONDS" />
</mail:inbound-channel-adapter>
<int:channel id="recieveEmailChannel">
<int:interceptors>
<int:wire-tap channel="logger"/>
</int:interceptors>
</int:channel>
<int:logging-channel-adapter id="logger" level="DEBUG"/>
<int:service-activator input-channel="recieveEmailChannel" ref="messageFactory" method="receive"/>
<bean id="messageFactory" class="src.com.project.service.factories.MessageFactory">
</bean>
This error generally is a configuration problem.
Conditions that might cause it include...
Misspelled method attribute in the <service-activator/> configuration
The method's not public
requires-reply="true" and the method returns void (like yours)
I am using Spring Integration 2.2.4 and I was having this problem. I saw another post that said that #Header does not work in some versions of Spring Integration. Unfortunately, I can't upgrade right now. So, the choices were to try using #Headers or use an expression. I used an expression and it is working for me...
<service-activator expression="#myService.serviceMethod(headers.customerKey, payload)"/>