Spring Integration: exception on receiving message - spring-integration

Within our Spring Integration application, when a message is received, an exception is thrown and the transformer does not receive the message.
I think it could be due to the content of the message, as messages of type String are processed correctly.
The following is the signature of the transformer for this message type:
#Transformer
public String transform(Message inboundMessage){
Have also tried
#Transformer
public String transform(Byte[] inboundMessage){
but in both instances, the following exception is thrown:
2013-10-14 07:21:33,547 D|DefaultMessageListenerContainer |Received message of type [class com.solacesystems.jms.message.SolTextMessage] from consumer [Cached JMS MessageConsumer: com.solacesystems.jms.SolQueueReceiver#13b5500] of session [Cached JMS Session: com.solacesystems.jms.SolSession#1fa0f19]
2013-10-14 07:21:33,579 W|DefaultMessageListenerContainer |Execution of JMS message listener failed, and no ErrorHandler has been set.
java.lang.RuntimeException: UTF-8 format error
at com.solacesystems.common.util.UTF8Util.getStringFromUTF8(UTF8Util.java:272) ~[sol-common-6.0.0.146.jar:na]
at com.solacesystems.jms.message.SolTextMessage.load(SolTextMessage.java:82) ~[sol-jms-6.0.0.146.jar:na]
at com.solacesystems.jms.message.SolTextMessage.getText(SolTextMessage.java:69) ~[sol-jms-6.0.0.146.jar:na]
at org.springframework.jms.support.converter.SimpleMessageConverter.extractStringFromMessage(SimpleMessageConverter.java:177) ~[spring-jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.support.converter.SimpleMessageConverter.fromMessage(SimpleMessageConverter.java:94) ~[spring-jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.integration.jms.ChannelPublishingJmsMessageListener.onMessage(ChannelPublishingJmsMessageListener.java:266) ~[spring-integration-jms-2.2.0.RC2.jar:na]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:537) ~[spring-jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:497) ~[spring-jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:468) ~[spring-jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:326) [spring-jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:264) [spring-jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1071) [spring-jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1063) [spring-jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960) [spring-jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at java.lang.Thread.run(Unknown Source) [na:1.6.0_06]
2013-10-14 07:21:33,579 D|SolMessageConsumer |Entering receive(), timeout: 1000
2013-10-14 07:21:34,391 D|SolMessageConsumer |Leaving receive()
Any help is greatly appreciated

It's not getting as far as the transformer. The problem is within the Solace library when Spring is calling getText...
java.lang.RuntimeException: UTF-8 format error
at com.solacesystems.common.util.UTF8Util.getStringFromUTF8(UTF8Util.java:272) ~[sol-common-6.0.0.146.jar:na]
at com.solacesystems.jms.message.SolTextMessage.load(SolTextMessage.java:82) ~[sol-jms-6.0.0.146.jar:na]
at com.solacesystems.jms.message.SolTextMessage.getText(SolTextMessage.java:69) ~[sol-jms-6.0.0.146.jar:na]
at org.springframework.jms.support.converter.SimpleMessageConverter.extractStringFromMessage(SimpleMessageConverter.java:177) ~[spring-jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
...
It looks like the library thinks the data is in UTF-8 format when it's not.

Related

Spring Integration WebFlux inboundGateway replyChannel for error response

Trying to use the replyChannel for sending an error response for the WebFlux.inboundGateway, however no response is sent from ErrorFlow and the client continues to wait for response. Kindly suggest.
return IntegrationFlows.from(WebFlux.inboundGateway("/some/uri")
.requestMapping(m -> m.methods(POST))
.requestPayloadType(SomeObject.class)
.replyChannel(webReplyChannel)
.errorChannel(appErrorChannel))
#Bean
public IntegrationFlow appErrorFlow() {
return IntegrationFlows.from(appErrorChannel())
.<ErrorMessage, Message<String>> transform(errorMessage -> MessageBuilder.withPayload("Error Response")
.copyHeaders(((MessagingException) errorMessage.getPayload()).getFailedMessage().getHeaders())
.build())
.get();
Exception:
2023-01-14 13:34:10,343 [reactor-http-nio-2 ] ERROR o.s.i.h.LambdaMessageProcessor - 1283c6fd42485bf5 Could not invoke the method 'public java.lang.Object com.xxxxxxxxxxx.xxxxx..ErrorFlowConfig$$Lambda$2129/0x0000000801ac3a00.transform(java.lang.Object)' due to a class cast exception, if using a lambda in the DSL, consider using an overloaded EIP method that takes a Class<?> argument to explicitly specify the type. An example of when this often occurs is if the lambda is configured to receive a Message<?> argument.
java.lang.ClassCastException: class com.xxxxxxx.model.dto.SomeObject cannot be cast to class org.springframework.messaging.support.ErrorMessage (com.xxxxxxx.model.dto.SomeObject is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader #32f93dff; org.springframework.messaging.support.ErrorMessage is in unnamed module of loader 'app')
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.integration.handler.LambdaMessageProcessor.processMessage(LambdaMessageProcessor.java:105)
at org.springframework.integration.transformer.AbstractMessageProcessingTransformer.transform(AbstractMessageProcessingTransformer.java:115)
at o
This is known framework limitation: https://github.com/spring-projects/spring-integration/issues/3984.
So, for now you have to do like this instead:
.transform(Message.class,
errorMessage ->
MessageBuilder.withPayload("Error Response")
.copyHeaders(((MessagingException) errorMessage.getPayload()).getFailedMessage().getHeaders())
.build())
Only those getFailedMessage().getHeaders() contain respective replyChannel and errorChannel headers.

Migration to EWS API for sending emails

I have the following code to send a email through EWS API,
ExchangeService service = new ExchangeService();
service.setUrl(new URI(**MyExchangeURL**));
ExchangeCredentials credentials = new WebCredentials(**UserName**, **Password**);
service.setCredentials(credentials);
EmailMessage message = new EmailMessage(service);
message.setSubject("EWS Test Mail");
message.setBody(MessageBody.getMessageBodyFromText("This is a test mail from EWS"));
message.getToRecipients().add("Test#gmail.com");
message.send();
With the above code, I facing a null pointer exception when message.send() is called.
Log:
Exception in thread "main" microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRequestException: The request failed. null
at microsoft.exchange.webservices.data.core.request.SimpleServiceRequestBase.internalExecute(SimpleServiceRequestBase.java:74)
at microsoft.exchange.webservices.data.core.request.MultiResponseServiceRequest.execute(MultiResponseServiceRequest.java:158)
at microsoft.exchange.webservices.data.core.ExchangeService.internalCreateItems(ExchangeService.java:598)
at microsoft.exchange.webservices.data.core.ExchangeService.createItem(ExchangeService.java:657)
at microsoft.exchange.webservices.data.core.service.item.Item.internalCreate(Item.java:245)
at microsoft.exchange.webservices.data.core.service.item.EmailMessage.internalSend(EmailMessage.java:147)
at microsoft.exchange.webservices.data.core.service.item.EmailMessage.send(EmailMessage.java:258)
at EWS.main(EWS.java:28)
Caused by: java.lang.NullPointerException
at microsoft.exchange.webservices.data.core.request.ServiceRequestBase.readResponse(ServiceRequestBase.java:369)
at microsoft.exchange.webservices.data.core.request.SimpleServiceRequestBase.internalExecute(SimpleServiceRequestBase.java:63)
... 7 more
When debugged further there is a mismatch in the attribute name.
In request, the attribute is contentType is setted in request. But while reading the response, we are getting Null as code used have Content-type. There is a mismatch in the attribute name being set and read.
Is anyone else facing this issue or any workaround?

What's the best way to handle reconnection with MqttPahoMessageHandler as token has now expired?

I have used the following example as a basis for my own code to publish to a MQTT server: https://github.com/spring-projects/spring-integration-samples/blob/master/basic/mqtt/src/main/java/org/springframework/integration/samples/mqtt/Application.java
I have a particular use case where the password is a token in particular a keycloak token which will expire. If for whatever reason the spring application loses connection with the MQTT server and tries to reconnect the token will have expired and an MqttSecurityException: Not authorized to connect exception will be thrown. I tried extending the method connectionLost in MqttPahoMessageHandler but as the MqttPahoClientFactory & IMqttAsyncClient are private final there is not much I can do. Wondering if there is any other approach I've not thought of or is the library just not meant to be used like this???
Thanks for any replies.
We get the MqttConnectOptions from the client factory each time we try to connect so you should be able to just update the password there.
If that doesn't work for some reason, open a new feature request.
EDIT
Regarding your comment, what's wrong with this?
#Bean
public MqttPahoClientFactory mqttClientFactory() {
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
MqttConnectOptions options = new MqttConnectOptions();
options.setServerURIs(new String[] { "tcp://localhost:1883" });
options.setUserName("guest");
options.setPassword("guest".toCharArray());
factory.setConnectionOptions(options);
return factory;
}
#Bean
public ApplicationRunner runner(MqttPahoClientFactory mqttClientFactory, MqttPahoMessageHandler handler) {
return args -> {
Thread.sleep(30_000);
System.out.println("Changing password");
mqttClientFactory.getConnectionOptions().setPassword("foo".toCharArray());
handler.stop();
handler.start();
};
}
foo
2020-03-10 17:42:33.560 INFO 95638 --- [iSampleConsumer] siSample
: foo sent to MQTT, received from MQTT
Changing password
foo
2020-03-10 17:43:08.705 ERROR 95638 --- [ask-scheduler-3] o.s.integration.handler.LoggingHandler
: org.springframework.messaging.MessageHandlingException: error occurred in message handler [bean 'mqttOutbound' for component 'mqttOutFlow.org.springframework.integration.config.ConsumerEndpointFactoryBean#1'; defined in: 'com.example.demo.So60610337Application'; from source: 'org.springframework.core.type.StandardMethodMetadata#79da8dc5']; nested exception is org.springframework.messaging.MessagingException: Failed to connect; nested exception is Bad user name or password (4), failedMessage=GenericMessage [payload=foo sent to MQTT, headers={id=4eab5b52-726f-7ea3-252d-77c4d0401cc8, timestamp=1583876588662}]
...
Caused by: Bad user name or password (4)

Getting error "Target object of type ...has no eligible methods for handling Messages"

I am using spring integration in my project.
I have recently added the below method for my service activator PQMessageHandler:
#SuppressWarnings("unchecked")
public Message<?> getDatabaseProductName(Message<?> inMessage){
Message<?> outMessage = null;
String databaseProductName = null;
try {
//get the database name.
databaseProductName = DataSourceUtils.getConnection(rd).getMetaData().getDatabaseProductName();
} catch (SQLException e) {
throw new RuntimeException(e);
}
Document mainDom = XmlParserUtil.convertString2Document((String)inMessage.getPayload());
//include database name in the response xml
Element databaseName = mainDom.getRootElement().addElement("databaseName");
databaseName.setText(databaseProductName);
MessageHeaders inMsgHdrs = inMessage.getHeaders();
MessageBuilder<?> msgBuilder = MessageBuilder.withPayload(mainDom.asXML()).copyHeaders(inMsgHdrs);
outMessage= msgBuilder.build();
logger.debug("\n ************************** External System Request Message ********************* \n");
logger.debug(outMessage);
logger.debug("\n ******************************************************************************** \n");
return outMessage;
}
I have configured the code that calls the above service activator is as follows:
<int:channel id="PQPutUserBAInformation-Add-DatabaseProductName" />
<int:service-activator input-channel="PQPutUserBAInformation-Add-DatabaseProductName"
output-channel="PQPutUserBAInformation-Database-Router"
ref="msgHandler"
method="getDatabaseProductName" />
<int:router input-channel="PQPutUserBAInformation-Database-Router" default-output-channel="PQPutUserBAInformation-Default-InsertUserId-Channel" resolution-required="false" expression="#xpath(payload, '//databaseName').toLowerCase().contains('db2')">
<int:mapping value="true" channel="PQPutUserBAInformation-DB2-Request"/>
</int:router>
The above code works fine without any issues in the development environment. Weirdly when I deploy my application in client environment, I am getting the following error:
2017-04-10 10:41:50,525 INFO [org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler] (ServerService Thread Pool -- 65) Shutting down ExecutorService 'taskScheduler'
2017-04-10 10:41:50,526 ERROR [org.springframework.web.context.ContextLoader] (ServerService Thread Pool -- 65) Context initialization failed: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.integration.config.ConsumerEndpointFactoryBean#345': Cannot resolve reference to bean 'org.springframework.integration.config.ServiceActivatorFactoryBean#61' while setting bean property 'handler'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.integration.config.ServiceActivatorFactoryBean#61': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Target object of type [class com.dsths.cs.awd.jobs.PQMessageHandler] has no eligible methods for handling Messages.
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329) [spring-beans-3.2.2.RELEASE.jar:3.2.2.RELEASE]
I am assuming that the recent changes are causing the issue. The log message is not clearly saying which service activator is causing the issue.
I googled about the error and confirmed that
1) There is no misspelled method attribute in the
configuration
2)The method is public
3)I haven't defined requires-reply="true" attribute in the configuration.
Any thoughts on troubleshooting the issue?
Figured out the root cause for the issue. The exception was due to EAR caching. Cleaning the EAR folder on Linux server and redeploying the war file freshly has worked out.

<int-jms:outbound-gateway> is not receiving reply messages

My <int-jms:outbound-gateway> is not sending messages to destination queue because of which i end up getting MessageTimeoutException.
I tried which worked perfectly and sent the messages which makes sure that i am getting correct messages on request-channel.
Also i see in logs that my outbound gatway is receiving the messages on requestCh1.
org.springframework.integration.jms.JmsOutboundGateway#0 received message: [Payload...]
I am really stuck and dont able to figure out why jms outbound gateway is not sending messages to destination queue.
Any help anybody ?
Config:
<int:publish-subscribe-channel id="requestCh1" />
<int:service-activator input-channel="requestCh1" ref="processor" method="processMsg"/>
<bean id="processor" class="com.processor.ProcessorImpl" />
<int-jms:outbound-gateway
id="eventPublisherGateway"
connection-factory="myConnectionFactory"
request-channel="requestCh1"
request-destination="qequestQueue"
reply-channel="responseCh1"
reply-destination="responseQueue"
receive-timeout="20000">
</int-jms:outbound-gateway>
Stacktrace:
07-15-2014 13:18:49 [threaPool.Thread-1] DEBUG AbstractMessageChannel$ChannelInterceptorList.preSend(334) | preSend on channel 'errorChannel', message: [Payload MessageTimeoutException content=org.springframework.integration.MessageTimeoutException: failed to receive JMS response within timeout of: 20000ms][Headers={id=7c81f473-e60e-30fa-b031-8106b3a2fff0, timestamp=1405444729344}]
07-15-2014 13:18:49 [threaPool.Thread-1] DEBUG AbstractMessageHandler.handleMessage(72) | (inner bean)#3dd4a538 received message: [Payload MessageTimeoutException content=org.springframework.integration.MessageTimeoutException: failed to receive JMS response within timeout of: 20000ms][Headers={id=7c81f473-e60e-30fa-b031-8106b3a2fff0, timestamp=1405444729344}]
07-15-2014 13:18:49 [threaPool.Thread-1] ERROR LoggingHandler.handleMessageInternal(145) | org.springframework.integration.MessageTimeoutException: failed to receive JMS response within timeout of: 20000ms
at org.springframework.integration.jms.JmsOutboundGateway.handleRequestMessage(JmsOutboundGateway.java:667)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:170)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.invokeHandler(BroadcastingDispatcher.java:160)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.dispatch(BroadcastingDispatcher.java:142)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:223)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:109)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:44)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:94)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendMessage(AbstractReplyProducingMessageHandler.java:260)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendReplyMessage(AbstractReplyProducingMessageHandler.java:241)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.produceReply(AbstractReplyProducingMessageHandler.java:205)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleResult(AbstractReplyProducingMessageHandler.java:199)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:177)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.endpoint.PollingConsumer.handleMessage(PollingConsumer.java:74)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:205)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.access$000(AbstractPollingEndpoint.java:55)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:149)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:146)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller$1.run(AbstractPollingEndpoint.java:284)
at org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:52)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Adding JMS Message this gateways is sending with correlation id.
JMS Message class: jms_text
JMSType: null
JMSDeliveryMode: 2
JMSExpiration: 0
JMSPriority: 4
JMSMessageID: ID:414d5120414344534430513720202020537502dd201b6c02
JMSTimestamp: 1405462485258
JMSCorrelationID:bf566441-8ccb-4620-afac-941cc4842a61
JMSDestination: queue://QMGR01/REQUESTQ
JMSReplyTo: queue://QMGR01/RESPONSEQ
JMSRedelivered: false
JMSXDeliveryCount:0
JMSXAppID:Websphere MQ Client for Java
JMS_IBM_PutApplType:28
timestamp:1405462384810
sequenceNumber:3
JMSXUserID:mqcls1
sequenceSize:4
JMS_IBM_PutTime:22574883
JMS_IBM_PutDate:20140715
<?xml version="1.0" encoding="UTF-8" standalone="no"?><Employee><empId>567</empId></<Employee>
Since you say that you get MessageTimeoutException and there is only one place in the JmsOutboundGateway where it is:
if (jmsReply == null) {
if (this.requiresReply) {
throw new MessageTimeoutException(message,
"failed to receive JMS response within timeout of: " + this.receiveTimeout + "ms");
}
else {
return null;
}
}
Hence your issue is around the reply not request.
I mean you send the message to the destination properly, but the other side doesn't send a reply to you to the responseQueue destination.
If you aren't interest in request/reply scenario and it's just enough to send messages, you can switch to the <int-jms:outbound-channel-adapter>.
If it isn't truth, show, please, the StackTrace to see where your MessageTimeoutException is caused.
UPDATE
Can this be because of JmsCorrelationId ?
Yes it can. The another part has to support the JMSCorrelationID property with a value from the request.
JmsOutboundGateway does the correlation by selector:
messageSelector = "JMSCorrelationID = '" + correlationId + "'";
...
messageConsumer = session.createConsumer(replyTo, messageSelector);

Resources