jpos : How to increase wait time to 40 secs so can handle delayed response messages - jpos

This is a scenario where the another system takes time to send the response back.
in this case I would like jpos to wait for for 40/45 secs before it could timeout.
below is the serious of log events:
Request send to jpos :
<log realm="channel/127.0.0.1:49142" at="2020-05-21T01:15:54.901" lifespan="1ms">
Jpos send out the message :
<log realm="channel/127.0.0.1:6269" a**t="2020-05-21T01:15:54.909"** lifespan="2ms">
but the channel timedout at 20 secs , the client requested the transaction is disconnected
<log realm="org.jpos.q2.iso.ChannelAdaptor" at="2020-05-21T01:16:19.593">
<warn>
channel-receiver-MIG_NT2_EP6-receive
Read timeout / EOF - reconnecting
</warn>
</log>
response received time is
<log realm="channel/127.0.0.1:6269" at="2020-05-21T01:16:32.610" lifespan="37771ms">
my channel is as below
<?xml version="1.0" ?>
<channel-adaptor name='MIG_NT2_EP6-channel' class="org.jpos.q2.iso.ChannelAdaptor" logger="Q2">
<channel class="org.jpos.iso.channel.NACChannel"
packager="org.jpos.iso.packager.GenericPackager"
logger="Q2"
header="6000000000"
>
<property name="packager-config" value="cfg/packager/AS280501.xml" debug="True" />
<property name="host" value="127.0.0.1" />
<property name="port" value="6336" />
<property name="timeout" value="180000"/>
</channel>
<in>MIG_NT2_EP6-send</in>
<out>MIG_NT2_EP6-receive</out>
<reconnect-delay>10000</reconnect-delay>
</channel-adaptor>
my mux
<?xml version="1.0" ?>
<mux class="org.jpos.q2.iso.QMUX" logger="Q2" name="MIG_NT2_EP6-AUTORESPONDER" debug="True">
<in>MIG_NT2_EP6-receive</in>
<out>MIG_NT2_EP6-send</out>
<ready>MIG_NT2_EP6-channel.ready</ready>
</mux>
txn manager
<txnmgr name="mpgs" class="org.jpos.transaction.TransactionManager" logger="Q2">
<property name="queue" value="MIG_NT2_EP6-TXNMGR"/>
<property name="sessions" value="2"/>
<property name="max-sessions" value="128"/>
<property name="debug" value="true"/>
<participant class="org.jpos.transaction.participant.QueryHost"/>
<participant class="org.jpos.transaction.participant.SendResponse"/>
</txnmgr>
server
<server class="org.jpos.q2.iso.QServer" logger="Q2" name="MIG_NT2_EP6-server-7336" realm="MIG_NT2_EP6-server-7336">
<attr name="port" type="java.lang.Integer">7336</attr>
<channel class="org.jpos.iso.channel.NACChannel"
packager="org.jpos.iso.packager.GenericPackager"
type="server"
logger="Q2"
header="6000000000"
>
<property name="packager-config" value="cfg/packager/CISascii.xml" debug="True" />
<property name="timeout" value="180000"/>
</channel>
<request-listener class="org.jpos.iso.IncomingListener" logger="Q2" realm="incoming-request-listener">
<property name="queue" value="MIG_NT2_EP6-TXNMGR" />
<property name="ctx.DESTINATION" value="MIG_NT2_EP6-AUTORESPONDER" />
</request-listener>
</server>
How can i increase the wait time to 40 secs so to handle the late arrived message
thanks in advance

The timeout you are receiving is not due to the timeout of the transaction but because of the timeout of the channel.
You have your channel with a timeout of 180 secs i.e. 3 minutes, so if no incoming traffic comes during 3 consecutive minutes, independent of the start of a transaction, the underlying socket will disconnect and that's what you are seeing here:
<log realm="org.jpos.q2.iso.ChannelAdaptor" at="2020-05-21T01:16:19.593">
<warn>
channel-receiver-MIG_NT2_EP6-receive
Read timeout / EOF - reconnecting
</warn>
</log>
If you don't have echo interchanges or you are testing I would disable that timeout to a long number or to 0 to disable it (just for testing, you don't want that in prod) you want that in prod but you need to ensure traffic by having echo messages at intervals lower than the channel timeout.
So the short answer would be, increase that timeout and the other timeout involved is hidden, it's the timeout in QueryHost which defaults to 30 secs.
If the response is expected to take less than a minute to arrive, you can configure a minute timeout as follows in your transaction manager:
<txnmgr name="mpgs" class="org.jpos.transaction.TransactionManager" logger="Q2">
<property name="queue" value="MIG_NT2_EP6-TXNMGR"/>
<property name="sessions" value="2"/>
<property name="max-sessions" value="128"/>
<property name="debug" value="true"/>
<participant class="org.jpos.transaction.participant.QueryHost">
<property name="timeout" value="60000"/>
</participant>
<participant class="org.jpos.transaction.participant.SendResponse"/>
</txnmgr>

Related

ActiveMQ DefaultMessageListenerContainer Why Only One Connection?

<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${mq.activemq.host}" />
<property name="userName" value="${mq.activemq.user}" />
<property name="password" value="${mq.activemq.pass}" />
<property name="maxThreadPoolSize" value="30" />
</bean>
<bean id="amqPooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
<property name="connectionFactory" ref="amqConnectionFactory" />
<property name="maxConnections" value="10" />
<property name="maximumActiveSessionPerConnection" value="300" />
<property name="idleTimeout" value="60000" />
</bean>
<bean id="queueListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="amqPooledConnectionFactory" />
<property name="destination" ref="queueDestination" />
<property name="messageListener" ref="queueAwareMessageListener" />
<property name="taskExecutor" ref="queueListenerTaskExecutor" />
<property name="concurrency" value="5-30" />
</bean>
What is the relationship between maxThreadPoolSize, maxConnections, maximumActiveSessionPerConnection, and concurrency?
Why I set maxConnections = 10, but Listener only one Connector in the Connections, can't increase more?
The number of consumers is correct. It has 5 with initialization,and gradually increases with change.
The bottom line regarding the number of connections which will be used is determined by the org.springframework.jms.listener.DefaultMessageListenerContainer which you have configured (since that is the only component here actually creating connections). As far as I can tell it will only ever create a single connection so using a connection pool here appears pointless. The concurrency parameter simply controls the concurrent number of consumers on the connection.
By setting maxConnections = 10 on the org.apache.activemq.pool.PooledConnectionFactory you are just limiting the size of the connection pool. However, since the queueListenerContainer won't ever call createConnection() more than once it doesn't really matter.
You can read about the maxThreadPoolSize of the org.apache.activemq.ActiveMQConnectionFactory in the ActiveMQ documentation.

How to join Spring JMS transactions from two different connection factories?

I am using different connection factories for sending and receiving messages, having trouble with partial commit issues incase of delivey failures. jms:message-driven-channel-adapter uses the receiveConnectionFactory ro receive the messages from the queue. jms:outbound-channel-adapter uses the deliverConnectionFactory to send the messages multiple to downstream queues. We have only one JmsTransactionManager which uses the receiveConnectionFactory and the jms:outbound-channel-adapter configured with session-transacted="true".
<beans>
<bean id="transactionManager"
class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="receiveConnectionFactory" />
</bean>
<bean id="receiveConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="hostName" value="${mq.host}" />
<property name="channel" value="${mq.channel}" />
<property name="port" value="${mq.port}" />
</bean>
</property>
<property name="sessionCacheSize" value="${receive.factory.cachesize}" />
<property name="cacheProducers" value="${receive.cache.producers.enabled}" />
<property name="cacheConsumers" value="${receive.cache.consumers.enabled}" />
</bean>
<bean id="deliverConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="hostName" value="${mq.host}" />
<property name="channel" value="${mq.channel}" />
<property name="port" value="${mq.port}" />
</bean>
</property>
<property name="sessionCacheSize" value="${send.factory.cachesize}" />
<property name="cacheProducers" value="${send.cache.producers.enabled}" />
<property name="cacheConsumers" value="${send.cache.consumers.enabled}" />
</bean>
<tx:advice id="txAdviceNew" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="send" propagation="REQUIRES_NEW" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="txAdviceNew" pointcut="bean(inputChannel)" />
<aop:advisor advice-ref="txAdviceNew" pointcut="bean(errorChannel)" />
</aop:config>
<jms:message-driven-channel-adapter
id="mdchanneladapter" channel="inputChannel" task-executor="myTaskExecutor"
connection-factory="receiveConnectionFactory" destination="inputQueue"
error-channel="errorChannel" concurrent-consumers="${num.consumers}"
max-concurrent-consumers="${max.num.consumers}" max-messages-per-task="${max.messagesPerTask}"
transaction-manager="transactionManager" />
<jms:outbound-channel-adapter
connection-factory="deliverConnectionFactory" session-transacted="true"
destination-expression="headers.get('Deliver')" explicit-qos-enabled="true" />
</beans>
When there is MQ exception on any one destination, the partial commit occurs and then the failure queue commit happens. I am looking to see if I am missing some configuration to join the transactions so that the partial commit never happens.
I tried with only one connection factory for both send and receive (receiveConnectionFactory) and the parital commit is not happening, everything works as expected.
I tried with only one connection factory for both send and receive (receiveConnectionFactory) and the parital commit is not happening, everything works as expected.
That's the right way to go in your case.
I see that your two ConnectionFactories are only different by their objects. Everything rest looks like the same target MQ server.
If you definitely can't live with only one ConnectionFactory, you should consider to use JtaTransactionManager or configure org.springframework.data.transaction.ChainedTransactionManager for two JmsTransactionManagers - one per connection factory.
See Dave Syer's article on the matter: https://www.javaworld.com/article/2077963/open-source-tools/distributed-transactions-in-spring--with-and-without-xa.html

Connection Timeout is not working - jaxws

I am trying to test the connection timeout for my injected client.
I am able to call the client , but the timeout is not working. Its taking default and taking more than 1 mins.My configuration below :-
Spring context :-
<bean id="myServiceClient" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
<property name="serviceInterface" value="au.com.my.service.employee.namespace.service"/>
<property name="namespaceUri" value="http://service.my.client.namespace.au/"/>
<property name="serviceName" value="MyWebService" />
<property name="endpointAddress" value="http://mywsdl.com?wsdl" />
<property name="wsdlDocumentUrl" value="http://mywsdl.com?wsdl" />
<property name="lookupServiceOnStartup" value="false" />
<property name="portName" value="myServicePort" />
<property name="customProperties" ref="jaxwsCustomProperties" />
</bean>
Custom properties:
<util:map id="jaxwsCustomProperties">
<entry key="com.sun.xml.internal.ws.request.timeout">
<value type="java.lang.Integer">1000</value>
</entry>
<entry key="com.sun.xml.internal.ws.connect.timeout">
<value type="java.lang.Integer">1000</value>
</entry>
<entry key="com.sun.xml.ws.request.timeout">
<value type="java.lang.Integer">1000</value>
</entry>
<entry key="com.sun.xml.ws.connect.timeout">
<value type="java.lang.Integer">1000</value>
</entry>
</util:map>
But, While I am calling this service its taking more than 1 mins. As per my understanding it should throw the connection timeout exception after 1 sec.
Please help me and advise if anything missed.
If you're expecting a Read timed out exception, try setting the javax.xml.ws.client.receiveTimeout property, that solved our similar issue.
As far as I understand, connect.timeout is used for how long the client is waiting to get a connection before throwing a connection refused error, socket timeout is how long the client is waiting for individual packets, see
ConnectionTimeout versus SocketTimeout.

Retry mechanism using Camel and ActiveMq - Retry Policy gets ignored

I am working on a retry mechanism using camel and activeMq. What I want to do is to start a retry mechanism if one of the servers I am calling is down, add the request into my queue and from hour to hour resend it to the server. Everything works fine except my Retry Policy that seems to be ignored (my requests are resent when they get into my queue and they are never added into the DLQ after the number of retries is reached)
My configuration looks as follows (Values are readed from a .cfg file):
<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-2.5.xsd">
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${activemq.broker.url}"/>
<property name="userName" value="${activemq.broker.username}"/>
<property name="password" value="${activemq.broker.password}"/>
<property name="redeliveryPolicy" ref="policy"/>
</bean>
<bean id="policy" class="org.apache.activemq.RedeliveryPolicy">
<property name="queue" value="*"/>
<property name="initialRedeliveryDelay" value="${activemq.redelivery.delay}"/>
<property name="redeliveryDelay" value="${activemq.redelivery.delay}"/>
<property name="useExponentialBackOff" value="false"/>
<property name="maximumRedeliveries" value="${activemq.number.of.redeliveries}"/>
</bean>
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
<property name="maxConnections" value="8"/>
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
<bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
<property name="transactionManager" ref="jmsTransactionManager"/>
<property name="transacted" value="true"/>
<property name="cacheLevelName" value="CACHE_CONSUMER"/>
<property name="concurrentConsumers" value="8"/>
</bean>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig"/>
</bean>
Camel route that calls my service:
<route id="addRegistrationRoute">
<from uri="direct:addRegistrationRoute"/>
<to uri="cxf:bean:addRegistrationEndpoint"/>
<onException>
<exception>java.net.ConnectException</exception>
<onWhen>
<el>${in.headers['previousRoute'] != 'registrationRetryRoute'}</el>
</onWhen>
<handled>
<constant>true</constant>
</handled>
<setBody>
<simple>${headers.request}</simple>
</setBody>
<removeHeaders pattern="*"/>
<to uri="activemq:queue:registrationRetryQueue"/>
<stop/>
</onException>
<onException>
<exception>org.apache.cxf.interceptor.Fault</exception>
<onWhen>
<el>${in.headers['previousRoute'] != 'registrationRetryRoute'}</el>
</onWhen>
<handled>
<constant>true</constant>
</handled>
<setBody>
<simple>${headers.request}</simple>
</setBody>
<removeHeaders pattern="*"/>
<to uri="activemq:queue:registrationRetryQueue"/>
<stop/>
</onException>
<onException>
<exception>javax.xml.soap.SOAPFault</exception>
<handled>
<constant>true</constant>
</handled>
</onException>
</route>
<route id="registrationRetryRoute">
<from uri="activemq:queue:registrationRetryQueue"/>
<setHeader headerName="previousRoute">
<simple>registrationRetryRoute</simple>
</setHeader>
<to uri="direct:addRegistrationRoute"/> <!-- Back to the initial flow. -->
</route>
If somebody can please tell me what I have did wrong in configuring activeMq I will be really thankful!
Regards,
Roxana
ActiveMQ pushes messages into DLQ only if you are throwing an error from your consumers (or message listeners). So try to catch your exception and throw it back so that retry policy will be enabled accordingly.

JMS rollback in WsO2 ESB 4.7.0

I have configured Apache ActiveMQ with transaction and CLIENT_ACKNOWLEDGE in WSO2 ESB 4.7.0. The axis2.xml config is :
<parameter name="transport.jms.SessionTransacted">true</parameter>
<parameter name="transport.jms.SessionAcknowledgement" locked="true">CLIENT_ACKNOWLEDGE</parameter>
I have a simple passthrough proxy with jms transport which passes the messages in the JMS queue to a jax-rs service. The proxy code is :
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="MediaMoveQueue"
transports="jms"
startOnLoad="true"
trace="enable">
<description/>
<target>
<inSequence>
<property name="messageType" value="application/json" scope="axis2"/>
<property name="ContentType" value="application/json" scope="axis2"/>
<send receive="JmsRollbackSequence">
<endpoint>
<address uri="http://192.168.1.2:9766/RestMediaMove_1.0.0/services/rest_media_move_i_f/restmediamoveif/hello"/>
</endpoint>
</send>
<log level="custom">
<property name="In MediaMoveQueue JMSERROR"
expression="get-property('JMSERROR')"/>
</log>
<switch source="get-property('JMSERROR')">
<case regex="true">
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
<log level="custom">
<property name="In MediaMoveQueue Transaction Action"
value="Rollbacked"/>
</log>
</case>
<case regex="false">
<log level="custom">
<property name="In MediaMoveQueue Transaction Action"
value="Committed"/>
</log>
</case>
<default>
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
<log level="custom">
<property name="In MediaMoveQueue Transaction Action default"
value="Rollbacked"/>
</log>
</default>
</switch>
</inSequence>
<outSequence>
<log level="full">
<property name="test" value="IN outsequence"/>
</log>
<send/>
</outSequence>
</target>
<parameter name="transport.jms.ContentType">
<rules>
<jmsProperty>contentType</jmsProperty>
<default>application/json</default>
</rules>
</parameter>
</proxy>
The JmsRollbackSequence sequence receives the reply from the jax-rs service and depending on the reply success or failure returned, I would like to rollback the JMS transaction. But if I set the property in the JmsRollbackSequence it has absolutely no effect ( I tried it first before using the sequence shown below). The transaction is never rolled back. The rollback works only if the property is set in the inSequence. Here is the code for the JmsRollbackSequence :
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="JmsRollbackSequence">
<property name="JMSERROR" value="true"/>
<log level="full">
<property name="test" value="IN JmsRollbackSequence"/>
</log>
</sequence>
So I tried to set up a property called JMSERROR in the JmsRollbackSequence and by reading it after the send mediator in the inSequence I thought I can roll back the transaction in the inSequence. But this does not work either. The switch case in inSequence is called before the property is set up in JmsRollbackSequence so when I read it it always returns null.
So my questions are :
1) Can we set
in a sequence? Why does it not work in JmsRollbackSequence?
2) As mediators are supposed to be called sequentially, why does the switch case in inSequence run before the JmsRollbackSequence has a chance to read the reply and set up the JMSERROR property?
"send" mediator is asynchronous : inSequence will continue his job and JMS transaction will be commited before the response arrive in your JmsRoolbackSequence.
use "callout" mediator for synchronous calls and create a faultSequence in your proxy to deal with errors and rollback your transaction :
<faultSequence>
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
</faultSequence>

Resources