java - Sending asynchronous PDU response with cloudhopper -
i have project uses cloudhopper 5.0.6 library hold smpp connection (3.4 version) , send or receive pdus. need modify default pduresopnse so, customized pdu processing organized extending defaultsmppsessionhandler following way:
public class smppsessionhandlercontroller extends defaultsmppsessionhandler { @override public pduresponse firepdurequestreceived(pdurequest pdurequest) { pdurequesthandler pdureqhandler = pdurequesthandler; pduresponse resultpduresponse = pdurequest.createresponse(); return processdefaultpduresponse(resultpduresponse); } private pduresponse processdefaultpduresponse(pduresponse pduresponse) { //do transformations here on pduresponse... return pduresponse; } } it works fine purposes:
- change result command status or pdu fields / tlv params
- don't send response current pdu request. firepdurequestreceived method must return null.
now need add delayed pdu response sending, here problems began. first try that:
@override public pduresponse firepdurequestreceived(pdurequest pdurequest) { pdurequesthandler pdureqhandler = pdurequesthandler; pduresponse resultpduresponse = pdurequest.createresponse(); return processdefaultpduresponse(resultpduresponse); } private pduresponse processdefaultpduresponse(pduresponse pduresponse) { try { thread.sleep(responsedelay); } catch (interruptedexception e) { throw new runtimeexception("response delay interrupted", e); } return pduresponse; } sleep current thread added delay sending response, invocation thread held responsedelay milliseconds. works fine if no more requests coming @ same time session. adding submit_sm load in same session caused error:
com.cloudhopper.smpp.type.smpptimeoutexception: unable response within [10000 ms] @ com.cloudhopper.smpp.impl.defaultsmppsession.sendrequestandgetresponse(defaultsmppsession.java:471) ~[ch-smpp-5.0.6.jar:5.0.6] @ com.cloudhopper.smpp.impl.defaultsmppsession.enquirelink(defaultsmppsession.java:439) ~[ch-smpp-5.0.6.jar:5.0.6] after searching in coudhopper sources found problem, excusive window lock action in defaultsmppsession class:
future = sendwindow.offer(pdu.getsequencenumber(), pdu, timeoutmillis, configuration.getrequestexpirytimeout(), synchronous); the problem in com.cloudhopper.commons.util.windowing.window class uses exclusive lock performing operations, impossible wait before returning pruresponse in 1 thread , making request another.
next try around returning null request processing (to drop request without sending response) , sending pduresponse manually com.cloudhopper.smpp.smppsession.sendresponsepdu(pduresponse) method. approach works awhile ends following exception:
com.cloudhopper.smpp.type.smppchannelexception: null @ com.cloudhopper.smpp.impl.defaultsmppsession.sendresponsepdu(defaultsmppsession.java:581) ~[ch-smpp-5.0.6.jar:5.0.6] @ com.svzn.autotest.smppclient.impl.cloudhopper.smppsendingmanager.sendpduresponse(smppsendingmanager.java:84) ~[smpp-client-1.0.1.jar:na] @ com.svzn.autotest.smppclient.impl.cloudhopper.util.sendpducommand.sendpduresponse(sendpducommand.java:80) [smpp-client-1.0.1.jar:na] @ com.svzn.autotest.smppclient.impl.cloudhopper.smppclientimpl.sendpduresponse(smppclientimpl.java:91) [smpp-client-1.0.1.jar:na] @ com.svzn.autotest.example.testng_aggr.lib.smpp.event.baseeventprocessor$1.run(baseeventprocessor.java:62) [test-classes/:na] @ java.util.concurrent.executors$runnableadapter.call(executors.java:439) [na:1.6.0_37] @ java.util.concurrent.futuretask$sync.innerrun(futuretask.java:303) [na:1.6.0_37] @ java.util.concurrent.futuretask.run(futuretask.java:138) [na:1.6.0_37] @ java.util.concurrent.scheduledthreadpoolexecutor$scheduledfuturetask.access$301(scheduledthreadpoolexecutor.java:98) [na:1.6.0_37] @ java.util.concurrent.scheduledthreadpoolexecutor$scheduledfuturetask.run(scheduledthreadpoolexecutor.java:206) [na:1.6.0_37] @ java.util.concurrent.threadpoolexecutor$worker.runtask(threadpoolexecutor.java:886) [na:1.6.0_37] @ java.util.concurrent.threadpoolexecutor$worker.run(threadpoolexecutor.java:908) [na:1.6.0_37] @ java.lang.thread.run(thread.java:662) [na:1.6.0_37] caused by: org.jboss.netty.handler.timeout.writetimeoutexception: null @ org.jboss.netty.handler.timeout.writetimeouthandler.<clinit>(writetimeouthandler.java:79) ~[netty-3.9.0.final.jar:na] @ com.cloudhopper.smpp.impl.defaultsmppclient.createsession(defaultsmppclient.java:259) ~[ch-smpp-5.0.6.jar:5.0.6] @ com.cloudhopper.smpp.impl.defaultsmppclient.doopen(defaultsmppclient.java:226) ~[ch-smpp-5.0.6.jar:5.0.6] @ com.cloudhopper.smpp.impl.defaultsmppclient.bind(defaultsmppclient.java:193) ~[ch-smpp-5.0.6.jar:5.0.6] @ com.svzn.autotest.smppclient.impl.cloudhopper.tasks.rebindtask.run(rebindtask.java:37) ~[smpp-client-1.0.1.jar:na] @ java.util.concurrent.executors$runnableadapter.call(executors.java:439) [na:1.6.0_37] @ java.util.concurrent.futuretask$sync.innerrunandreset(futuretask.java:317) [na:1.6.0_37] @ java.util.concurrent.futuretask.runandreset(futuretask.java:150) [na:1.6.0_37] @ java.util.concurrent.scheduledthreadpoolexecutor$scheduledfuturetask.access$101(scheduledthreadpoolexecutor.java:98) [na:1.6.0_37] @ java.util.concurrent.scheduledthreadpoolexecutor$scheduledfuturetask.runperiodic(scheduledthreadpoolexecutor.java:180) [na:1.6.0_37] @ java.util.concurrent.scheduledthreadpoolexecutor$scheduledfuturetask.run(scheduledthreadpoo lexecutor.java:204) [na:1.6.0_37 ] ... 3 common frames omitted have no idea how fix error or send asynchronus pduresponse in same session way. have ideas that?
finally, found problem. issue in incorrect synchronization block, blocked parallel asyncronus event processing (sending pdu responses) , processing requests , responses without dealy in usual way.
its ok invoke com.cloudhopper.smpp.smppsession.sendresponsepdu(pduresponse) method in 1 thread , woking requests , responses extending defaultsmppsessionhandler one. everything'll processed in same session.
update: here's implementation used handle pdu requests:
public class smppsessionhandlercontroller extends defaultsmppsessionhandler { private static final logger log = loggerfactory.getlogger(smppsessionhandlercontroller.class); private volatile pduhandler pduhandler; private pduresponsehandler pduresponsehandler; private pdurequesthandler pdurequesthandler; public smppsessionhandlercontroller() { super(log); } public pduhandler getpduhandler() { return pduhandler; } public void setpduhandler(pduhandler pduhandler) { this.pduhandler = pduhandler; } public pduresponsehandler getpduresponsehandler() { return pduresponsehandler; } public void setpduresponsehandler(pduresponsehandler pduresponsehandler) { this.pduresponsehandler = pduresponsehandler; } public pdurequesthandler getpdurequesthandler() { return pdurequesthandler; } public void setpdurequesthandler(pdurequesthandler pdurequesthandler) { this.pdurequesthandler = pdurequesthandler; } @override public void fireexpectedpduresponsereceived(pduasyncresponse pduasyncresponse) { log.trace("handling response pdu: {}", pduasyncresponse); pduasyncresponse.getresponse().setreferenceobject(pduasyncresponse.getrequest().getreferenceobject()); processpduresponse(pduasyncresponse.getresponse()); } @override public void fireunexpectedpduresponsereceived(pduresponse pduresponse) { log.warn("handling unexpected response pdu: {}", pduresponse); processpduresponse(pduresponse); } @override public boolean firepdureceived(pdu pdu) { pduhandler currpduhandler = pduhandler; if (currpduhandler != null) { smpppdu smpppdu = pdutoapiconverter.converttoapiobject(pdu); currpduhandler.handlepdureceived(smpppdu); } // default handling accept pdu processing chain return true; } public void firepdurequestexpired(pdurequest pdurequest) { super.firepdurequestexpired(pdurequest); } private void processpduresponse(pduresponse pduresponse) { handlerscontexthelper referenceobj = (handlerscontexthelper) pduresponse.getreferenceobject(); if (referenceobj != null) { referenceobj.getsequenceidholder().addreceivedsequenceid(pduresponse.getsequencenumber()); } pduresponsehandler pduresphandler = pduresponsehandler; if (pduresphandler != null) { smpppduresponse smpppduresponse = pdutoapiconverter.converttoapiresponse(pduresponse); if (smpppduresponse != null) { pduresphandler.handlepduresponse(smpppduresponse); } } if (referenceobj != null) { referenceobj.getsequenceidholder().checksentandreceivedclosed(); } } @override public pduresponse firepdurequestreceived(pdurequest pdurequest) { pdurequesthandler pdureqhandler = pdurequesthandler; pduresponse resultpduresponse = pdurequest.createresponse(); if (pdureqhandler == null) { return resultpduresponse; } pduresponse defaultpduresponse = pdurequest.createresponse(); smpppdurequest smpppdurequest = pdutoapiconverter.converttoapirequest(pdurequest); smpppduresponse defaultsmpppduresponse = pdutoapiconverter.converttoapiresponse(defaultpduresponse); if (smpppdurequest == null || defaultsmpppduresponse == null) { return resultpduresponse; } smpppduresponse resultsmpppduresponse = pdureqhandler.handlepdurequest(smpppdurequest, defaultsmpppduresponse); if (resultsmpppduresponse == null) { return null; } pduresponse convertedpduresponse = apitopduconverter.converttopduresponse(resultsmpppduresponse); if (convertedpduresponse == null) { return resultpduresponse; } if (!resultpduresponse.getclass().isassignablefrom(convertedpduresponse.getclass())) { return resultpduresponse; } return convertedpduresponse; } } wich added clowdhopper smpp client this
smppsession session = smppclient.bind(smppsessionconfiguration_instance, smppsessionhandlercontroller_instance ); i defined custom interfaces pduhandler pdurequesthandler , pduresponsehandler handle special cases of smpp events, can see smppsessionhandlercontroller delegate invocations 1 of them.
using method
public pduresponse firepdurequestreceived(pdurequest pdurequest) defiend in smppsessionhandler can send response want in synch mode. if want in asynch mode, return null pduresponse , use smppsession.sendresponsepdu(pdu) instead current or other thread.
All the layers can be managed very easily allowing the users to upgrade the core nodes for handling SMS traffic in the most seamless manner. Contact us: +91-8349217770 or Sales@Msgclub.Net / Sales@smsprovider.com
ReplyDeleteSMPP Software