Thread: [Asterisk-java-users] AsteriskServer as a service / in a spring context ?
Brought to you by:
srt
From: Gaëtan M. <gm...@ea...> - 2008-04-05 13:39:11
Attachments:
patch-service-oriented.txt
|
Hi Stefan We are using the AsteriskServerImpl class inside a spring application. We however faced some problems as the stock AsteriskServerImpl seemed no so spring-friendly. The main problems I faced are the following: 1/ There is no "start" method on the server. Instead it starts "on demand" when sending the first action, or worst, when one adds a listener on it. That means that the server automatically tries to start "too early" when spring wires the listener into it. Is there a good reason to call initializeIfNeeded() in the addAsteriskServerListener() method (and as a consequence have it potentially throw a MCE) ? 2/ If that very first connection fails in "initializeIfNeeded", then the method throws an MCE that escalades to the addAsteriskServerListener method and eventually reaches the spring context factory. As a result, the server is down and won't start again until we try to send something. Moreover as the exception was thrown before the actual listeners.add() call, our listener is eventually not added. So the application completely fails to start in spring if it can't reach asterisk while starting. NB: However if later asterisk is stopped, everything is fine as the connection handles the reconnection automatically. So I originally worked around this using a patched ConnectionImpl that simply started in the fake "RECONNECTING" state :) I recently tried to clean all these modifications to ease my weekly merge against your trunk revision. Here is a patch against head as of today. This is clearly not a request for inclusion but just meant to illustrate how I worked around the problem. Indeed it is really not correct regarding object programing patterns but only meant to be small and not intrusive so you can easily see what I'm trying to implement. If you think that kind of functionality is interesting, maybe I could write some cleaner code and submit it ? In that event, I'd like to have your idea on the subject before I start. I personally think common functionality should then be moved to an abstract AbstractAsterikServerImpl class, with the child AsteriskServerImpl class maintaining the same behavior and semantic as the current one, and another one implementing the other "service- oriented" approach. What do you think ? Kind regards Thanks for your great work. Gaetan |
From: Maciek T. <mlo...@gm...> - 2008-04-05 17:08:23
|
Hey all, I'm using gnudialer which defines event named ManagerEvent in Asterisk Manager Interface (there is patch to manager.c file- http://dynx.net/ASTERISK/gnudialer/manager.c.both-patches.txt). Currently I'm developing some application that monitors events form * and there is some problem, because when ManagerEvent reaches my application on Std.err I've got: ---- 008-04-05 18:44:00 org.asteriskjava.manager.internal.EventBuilderImpl buildEvent INFO: No event class registered for event type 'crm_disporecord', attributes: {body=Agent: 300|Dispo: 4|Transfer: TRANSFER|Campaign: test5|Leadid: 185|Channel: Local/693595766@gd-out-9f42,1, event=CRM_DispoRecord, privilege=user,all} ---- My question is: how to define new Asterisk event type (this is _not_ user event) without recompiling asterisk-java code? Is there any way to do this. I know there is registerEventClass method in ManagerReaderImpl class. How to use it? Regards, Maciek |
From: Stefan R. <ste...@re...> - 2008-04-06 08:24:00
Attachments:
signature.asc
|
Hi, though the registerUserEvent method in ManagerConnection is intended primarily for user events you can also use it to register "normal" events. The approach is to implement a class for the CRM_DispoRecord event and register it. Just have a look at the other events to see how to do that. There is no need to recompile or modify the Asterisk-Java jar to add new events. =Stefan -- reuter network consulting Neusser Str. 110 50760 Koeln Germany Telefon: +49 221 1305699-0 Telefax: +49 221 1305699-90 E-Mail: ste...@re... Jabber: ste...@re... WWW: http://www.reucon.com Steuernummern 215/5140/1791 USt-IdNr. DE220701760 |
From: Maciek T. <mlo...@gm...> - 2008-04-06 09:44:51
|
Hi, Stefan thanks for the advice. I've implemented a CRM_DispoRecord and registered it. And now I'm able to handle this event. I've done this in this way: --- CRM_DispoRecordEvent.java file public class CRM_DispoRecordEvent extends ManagerEvent{ /** * class body definition */ } --- Main application file //.... connection = factory.createManagerConnection(); try { connection.login(); connection.registerUserEventClass(CRM_DispoRecordEvent.class); } catch (Exception ex) { ex.printStackTrace(); } //.... Most important thing was to extend ManagerEvent not UserEvent class in CRM_DispoRecordEvent. Regards, Maciek -----Original Message----- From: ast...@li... [mailto:ast...@li...] On Behalf Of Stefan Reuter Sent: Sunday, April 06, 2008 10:24 AM To: ast...@li... Subject: Re: [Asterisk-java-users] Gnudialer and asterisk-java, new event types Hi, though the registerUserEvent method in ManagerConnection is intended primarily for user events you can also use it to register "normal" events. The approach is to implement a class for the CRM_DispoRecord event and register it. Just have a look at the other events to see how to do that. There is no need to recompile or modify the Asterisk-Java jar to add new events. =Stefan -- reuter network consulting Neusser Str. 110 50760 Koeln Germany Telefon: +49 221 1305699-0 Telefax: +49 221 1305699-90 E-Mail: ste...@re... Jabber: ste...@re... WWW: http://www.reucon.com Steuernummern 215/5140/1791 USt-IdNr. DE220701760 |
From: Stefan R. <ste...@re...> - 2008-04-06 09:57:51
Attachments:
signature.asc
|
Thanks for reporting your success. You can register the event even before logging in, so you receive the events right from the beginning, e.g. connection.registerUserEventClass(CRM_DispoRecordEvent.class); connection.login(); =Stefan Maciek Tokarski wrote: > Hi, > Stefan thanks for the advice. I've implemented a CRM_DispoRecord and > registered it. And now I'm able to handle this event. > > I've done this in this way: > > --- CRM_DispoRecordEvent.java file > > public class CRM_DispoRecordEvent extends ManagerEvent{ > /** > * class body definition > */ > } > > > --- Main application file > > //.... > connection = factory.createManagerConnection(); > > try { > connection.login(); > connection.registerUserEventClass(CRM_DispoRecordEvent.class); > } catch (Exception ex) { > ex.printStackTrace(); > } > //.... > > Most important thing was to extend ManagerEvent not UserEvent class in > CRM_DispoRecordEvent. > > > Regards, Maciek > > > > -----Original Message----- > From: ast...@li... > [mailto:ast...@li...] On Behalf Of > Stefan Reuter > Sent: Sunday, April 06, 2008 10:24 AM > To: ast...@li... > Subject: Re: [Asterisk-java-users] Gnudialer and asterisk-java, new event > types > > Hi, > > though the registerUserEvent method in ManagerConnection is intended > primarily for user events you can also use it to register "normal" > events. The approach is to implement a class for the CRM_DispoRecord > event and register it. Just have a look at the other events to see how > to do that. > There is no need to recompile or modify the Asterisk-Java jar to add new > events. > > =Stefan > -- reuter network consulting Neusser Str. 110 50760 Koeln Germany Telefon: +49 221 1305699-0 Telefax: +49 221 1305699-90 E-Mail: ste...@re... Jabber: ste...@re... WWW: http://www.reucon.com Steuernummern 215/5140/1791 USt-IdNr. DE220701760 |
From: Stefan R. <ste...@re...> - 2008-04-06 08:22:11
Attachments:
signature.asc
|
Hi, > 1/ There is no "start" method on the server. Instead it starts "on > demand" when sending the first action, or worst, when one adds a > listener on it. > That means that the server automatically tries to start "too early" when > spring wires the listener into it. I think we can fix this by some refactoring and provide an implementation that initializes automatically and one that throws MCE or IllegalStateException when a method is called that requires a connection and it is not yet initialized. A simple solution might be to replace to calls to initializeIfNeeded() by calls to a new protected method called checkInitialize() of similar, that can be overridden by subclasses and either throw an exception or perform the initialization if its not yet initialized. > Is there a good reason to call initializeIfNeeded() in the > addAsteriskServerListener() method (and as a consequence have it > potentially throw a MCE) ? The idea behind this that if you register a listener and the object has not yet been initialized you won't receive any events. In fact the public initialize() method was only added later on, originally AsteriskServer was meant to work out of the box with as few lines of code as possible. - Maybe it's a bit too smart now :-) > 2/ If that very first connection fails in "initializeIfNeeded", then the > method throws an MCE that escalades to the addAsteriskServerListener > method and eventually reaches the spring context factory. As a result, > the server is down and won't start again until we try to send something. > Moreover as the exception was thrown before the actual listeners.add() > call, our listener is eventually not added. > So the application completely fails to start in spring if it can't reach > asterisk while starting. > > NB: However if later asterisk is stopped, everything is fine as the > connection handles the reconnection automatically. So I originally > worked around this using a patched ConnectionImpl that simply started in > the fake "RECONNECTING" state :) This is a bit harder. Usually I prefer things to fail early so you notice if you put in the wrong hostname or credentials. I understand that there are situations where this is not the required behavior. As you point out preventing the application from deploying due to Asterisk maintainance is not acceptable. To solve this issue we may have to add a feature to force a ManagerConnection to keep connecting. This won't probably look much different from the RECONNECTING hack, except for that it's hidden :-) How should we proceed? =Stefan -- reuter network consulting Neusser Str. 110 50760 Koeln Germany Telefon: +49 221 1305699-0 Telefax: +49 221 1305699-90 E-Mail: ste...@re... Jabber: ste...@re... WWW: http://www.reucon.com Steuernummern 215/5140/1791 USt-IdNr. DE220701760 |
From: Gaëtan M. <gm...@ea...> - 2008-04-06 10:35:17
|
Hi Thanks for your time. >> 1/ There is no "start" method on the server. Instead it starts "on >> demand" when sending the first action, or worst, when one adds a >> listener on it. > > I think we can fix this by some refactoring and provide an > implementation that initializes automatically and one that throws > MCE or > IllegalStateException when a method is called that requires a > connection > and it is not yet initialized. Indeed I think some minor refactoring is the best option. In fact that's what I initially did but I later reworked this to keep a minimal patch against trunk. The AsteriskServerImpl class should of course maintain the old behavior, hence my idea to move common code in an abstract superclass than requires a connection object, and then handle connection creation/ initialization specifics in the subclasses. > > A simple solution might be to replace to calls to initializeIfNeeded() > by calls to a new protected method called checkInitialize() of > similar, > that can be overridden by subclasses and either throw an exception or > perform the initialization if its not yet initialized. Lol, checkinitialize() was exactly the name I used but once again I renamed it and wrapped it in InitializeifNeeded to reduce the patch size ;) However it should not throw an exception when called from addAsteriskServerListener, or, at least, addAsteriskServerListener should catch it in the service oriented implementation. The AsteriskServer interface should however still declare it throws an MCE but we'll know that it won't happen with the service oriented implementation. > >> Is there a good reason to call initializeIfNeeded() in the >> addAsteriskServerListener() method (and as a consequence have it >> potentially throw a MCE) ? > > The idea behind this that if you register a listener and the object > has > not yet been initialized you won't receive any events. In fact the > public initialize() method was only added later on, originally > AsteriskServer was meant to work out of the box with as few lines of > code as possible. - Maybe it's a bit too smart now :-) And that's really great for starters. We must keep the old behaviour. Another problem is that automatically starting the connection before adding the listener could also cause lost events (ie my "server initialized" event). > > >> 2/ If that very first connection fails in "initializeIfNeeded", >> then the >> method throws an MCE that escalades to the addAsteriskServerListener >> method and eventually reaches the spring context factory. As a >> result, >> the server is down and won't start again until we try to send >> something. >> Moreover as the exception was thrown before the actual >> listeners.add() >> call, our listener is eventually not added. >> So the application completely fails to start in spring if it can't >> reach >> asterisk while starting. >> > > This is a bit harder. Usually I prefer things to fail early so you > notice if you put in the wrong hostname or credentials. I understand > that there are situations where this is not the required behavior. As > you point out preventing the application from deploying due to > Asterisk > maintainance is not acceptable. > To solve this issue we may have to add a feature to force a > ManagerConnection to keep connecting. This won't probably look much > different from the RECONNECTING hack, except for that it's hidden :-) In the demo patch I attached, I now start a background thread whose aim is to try and force the first connection in a loop (and swallow MCE exception for that purpose). > > How should we proceed? > If you're interested in this kind of patch I can try and write it. This should be fairly easy. Gaetan |