How can I send a notification message from server to all clients in WCF (broadcast you can say)? - wcf

I want to send notification message every second from net tcp WCF service to all clients,
Broadcast you can say?
After the helpful answers
I wrote the following method that will send notifications (heartbeat) to all connected users
foreach (IHeartBeatCallback callback in subscribers)
{
ThreadPool.QueueUserWorkItem(delegate(object state)
{
ICommunicationObject communicationCallback = (ICommunicationObject)callback;
if (communicationCallback.State == CommunicationState.Opened)
{
try
{
callback.OnSendHeartBeat(_heartbeatInfo.message, _heartbeatInfo.marketstart,_heartbeatInfo.marketend, _heartbeatInfo.isrunning, DateTime.Now);
}
catch (CommunicationObjectAbortedException)
{
Logger.Log(LogType.Info, "BroadCast", "User aborted");
communicationCallback.Abort();
}
catch (TimeoutException)
{
Logger.Log(LogType.Info, "BroadCast", "User timeout");
communicationCallback.Abort();
}
catch (Exception ex)
{
Logger.Log(LogType.Error, "BroadCast", "Exception " + ex.Message + "\n" + ex.StackTrace);
communicationCallback.Abort();
}
}
else
{
DeletionList.Add(callback);
}
}
);
}
I am worried about calling the callback method as the client may close his application, but I handled it using the try catch, decrease the timeout, and send the broad cast in parallel, so is that sufficient?

You'll need to setup a callback service; I wrote a simple beginners guide a while back

In order to do that, you need to create and mantain a list of all connected clients (the general practice to fo this is creating LogIn and LogOut methods to create and manage a list of object representing your clients incuding their CallbackContext).
Then, with a System.Time.Timers, you can loop through the connected client list and send the notification.
Tip. this method could also act as a Keep-Alive or Hear-Beat method (if this isn't it's purpose by design) by adding the possiblity to remove clients from your list if the service cannot send the callback to them.

Related

Raising/Clearing SNMP alarm best practices

I am currently having an application where SNMP ALARMS are raised when my program is not able to reach an external API. I clear the alarm when ever i am successfully getting a response back from the API .
Below is the code for the same .
// Call Webservice to check the external API is up or not
logger.debug("Sending trap data Clear Alarm {}" , trapData);
AlarmTrap.INTERFACE_SMSC_STATUS.clear(trapData);
}
catch(CustomException e)
{
AlarmTrap.INTERFACE_SMSC_STATUS.raise(trapData);
logger.error("Error " + e);
throw e;
}
As you can see for every successful response i am clearing the alarm . Though there is no impact on the current execution as SNMP server discard same kind of alarms . I want to know if it is good practice or not . And whether SNMP protocol itself handles duplicate alarms and are not sent across to network .
If you do not want to send duplicate alarms for consecutive success API responses, you can create a AtomicBoolean class variable - isErrorAlert that only SNMP clear TRAP shall be invoked if the isErrorAlert = true.
AtomicBoolean isErrorAlert = new AtomicBoolean();
try{
//API Success case
if(isErrorAlert.compareAndSet(true, false)){
//send clear trap only if the error case is occured
}
} catch(Exception e) {
//Fail case
isErrorAlert.set(true);
}
References:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html

WCF Service proxy - Both Close() and Abort functions getting called

I have the below code to call a WCF proxy:-
var client = new ServiceClientProxy();
try
{
var documents = client.GetDocuments();
client.Close();
if(documents.Length > 50)
{
throw new Exception("Too many Documents");
}
else if(documents.Length <10)
{
throw new Exception("Too many Documents");
}
else
{
return documents;
}
}
catch(exception ex)
{
client.Abort();
}
Here If the documents count that we get from service is more than 50 or less than 10, in that case we will be calling both Close() as well as the Abort functions on client.Is this expected way of calling WCF service proxy?
Anyone please suggest if there is some better way handling this.
Also is it a better approach to close the client connection immediately after the call or do we need to wait till we have completely used the response properties and close the connection at end?
Also is it a better approach to close the client connection
immediately after the call or do we need to wait till we have
completely used the response properties and close the connection at
end?
Depends on if you need to make subsequent calls to the service. If not then by all means close the connection.
Is this expected way of calling WCF service proxy? Anyone please
suggest if there is some better way handling this.
No. To handle a problem that is baked into WCF you could should actually be structured like this:
Documents documnts = null;
try
{
var client = new ServiceClientProxy();
documents = client.GetDocuments();
}
finally
{
try
{
if (client.State != CommunicationState.Closed)
client.Close();
}
catch
{
client.Abort();
};
};
if (documents.Length > 50)
{
throw new Exception("Too many Documents");
}
else if (documents.Length < 10)
{
throw new Exception("Too many Documents");
}
else
{
return documents;
}
If you want to truly understand the 'why' I would highly recommend reading this series of articles. They will clear up the Close / Abort portion of your problem.
http://blogs.msmvps.com/p3net/2014/02/02/a-smarter-wcf-service-client-part-1/
http://blogs.msmvps.com/p3net/2014/02/09/a-smarter-wcf-service-client-part-2/
http://blogs.msmvps.com/p3net/2014/02/23/a-smarter-wcf-service-client-part-3/
http://blogs.msmvps.com/p3net/2014/03/15/a-smarter-wcf-service-client-part-4/
Another other things I should point out with the code you've provided is exceptions should be exceptional.
Using exceptions for what I would considered to be business logic is usually not the right thing to do. Consider the approach where you return a structured result instead. Perhaps in your case it make sense though.
HTH

Lync Client API exception - Specified method is not supported

I am developing simple chat application using CWE which sends messages by using contextual data. I'm having "Specified method is not supported" exception message. This exception occurs when I try to start chat with group. one-to-one chat works fine with no exception. since I'm having same code on both sender & receiver side, I'm confused that how to make this work. Please help.
My code snippet as as follows.
void method1()
{
//
//here I have code to send an IM saying "lets chat in extension window"
//
try
{
Dictionary<ContextType, object> context = new Dictionary<ContextType, object>();
context.Add(ContextType.ApplicationId, "{1226271D-64C9-4F24-B416-E6A583F45A1C}");
context.Add(ContextType.ApplicationData, "initial_data_request");
try { IAsyncResult res = conversation.BeginSendInitialContext(context, null, null); }
catch (Exception e1)
{
MessageBox.Show(e1.Data+"\n\n"+e1.Message);
}
}
catch (Exception ee)
{
MessageBox.Show("Client Platform Exception: " + ee.Message);
}
}
This is the method I call when my application starts. It is supposed to send initial context so that receiver clients when receive this should open my extension application.
I found the answer. It is showing that exception because contextual data will not work in a group conversation.
Found the related thread here..
http://social.msdn.microsoft.com/Forums/lync/en-US/b4e46648-7097-4348-8327-6864f1c12ab2/contextdata-in-a-group-conversation?forum=communicatorsdk

How to make an Attended call transfer with UCMA

I'm struggling with making a call transfer in a UMCA IVR app I've built. This is not using Lync.
Essentially, I have an established call from an outside user and as part of the IVR application, they select an option to be transferred. This transfer is to a configured outside number (ie: Our Live Operator). What I want to do is transfer the original caller to the outside number, and if a valid transfer is established, I want to terminate the original call. If the transfer isn't established, I want to send control back to the IVR application to handle this gracefully.
My problem is my EndTransferCall doesn't get hit when the transfer is established. I would have expected it to hit, set my AutoResetEvent and return a True, and then in my application I can disconnect the original call. Can somebody tell me what I'm missing here?
_call is an established AudioVideoCall. My application calls the Transfer method
private AutoResetEvent _waitForTransferComplete = new AutoResetEvent(false);
public override bool Transfer(string number, int retries = 3)
{
var success = false;
var attempt = 0;
CallTransferOptions transferOptions = new CallTransferOptions(CallTransferType.Attended);
while ((attempt < retries) && (success == false))
{
try
{
attempt++;
_call.BeginTransfer(number, transferOptions, EndTransferCall, null);
// Wait for the transfer to complete
_waitForTransferComplete.WaitOne();
success = true;
}
catch (Exception)
{
//TODO: Log that the transfer failed
//TODO: Find out what exceptions get thrown and catch the specific ones
}
}
return success;
}
private void EndTransferCall(IAsyncResult ar)
{
try
{
_call.EndTransfer(ar);
}
catch (OperationFailureException opFailEx)
{
Console.WriteLine(opFailEx.ToString());
}
catch (RealTimeException realTimeEx)
{
Console.WriteLine(realTimeEx.ToString());
}
finally
{
_waitForTransferComplete.Set();
}
}
Is the behavior the same if you don't use the _waitForTransferComplete object? You shouldn't need it - it should be fine that the method ends, the event will still be raised. If you're forcing synchronous behavoir in order to fit in with the rest of the application though, try it like this:
_call.EndTransfer(
_call.BeginTransfer (number,transferOptions,null,null)
);
I'm just wondering if the waiting like that causes a problem if running on a single thread or something...

JMS Expiration after it has been receive not working

The title might be confusing but this is what I want to accomplish. I want to send a jms message from 1 ejb to another, the 2nd ejb has a message listener and this is now working properly. But I wanted the 1st ejb to create a temporary destination queue where the 2nd ejb would respond - this is also working properly.
My problem is in the 2nd ejb, it's calling a 3rd party web service that on some occasion would respond after a long time, and the temporary queue should expire on that time. But the problem is it doesn't according to java.net: http://java.net/projects/mq/lists/users/archive/2011-07/message/22
The message hasn't been delivered to a client and it expires -- in this case, the message is deleted when TTL is up.
The message is delivered to the JMS client (it's in-flight). Once this happens, since control is handed to the jms client, the broker cannot expire the message.
Finally, the jms client will check TTL just before it gives the message to the user application. If it's expired, we will not give it to the application and it will send a control message back to the broker indicating that the message was expired and not delivered.
So, it was received but no reply yet. Then on the time where it would write to the temporary queue it should already be expired but for some reason I was still able to write to the queue and I have the ff in my imq log:
1 messages not expired from destination jmsXXXQueue [Queue] because they have been delivered to client at time of the last expiration reaping
Is there another implementation where I can detect if the temporary queue is already expired? So that I can perform another set of action? Because my problem right now is ejb2 respond late and there is no more jms reader from ejb1 because it's already gone.
It works now, my solution was to wrap the 1st Stateless bean (the one where the first jms message originates) inside a bean managed transaction. See code below:
#Stateless
#TransactionManagement(TransactionManagementType.BEAN)
#LocalBean
public class MyBean {
public void startProcess() {
Destination replyQueue = send(jmsUtil, actionDTO);
responseDTO = readReply(jmsUtil, replyQueue, actionDTO);
jmsUtil.dispose();
}
public Destination send(JmsSessionUtil jmsUtil, SalesOrderActionDTO soDTO) {
try {
utx.begin();
jmsUtil.send(soDTO, null, 0L, 1,
Long.parseLong(configBean.getProperty("jms.payrequest.timetolive")), true);
utx.commit();
return jmsUtil.getReplyQueue();
} catch (Exception e) {
try {
utx.rollback();
} catch (Exception e1) {
}
}
return null;
}
public ResponseDTO readReply(JmsSessionUtil jmsUtil, Destination replyQueue,
SalesOrderActionDTO actionDTO) {
ResponseDTO responseDTO = null;
try {
utx.begin();
responseDTO = (ResponseDTO) jmsUtil.read(replyQueue);
if (responseDTO != null) {
//do some action
} else { // timeout
((TemporaryQueue) replyQueue).delete();
jmsUtil.dispose();
}
utx.commit();
return responseDTO;
} catch (Exception e) {
try {
utx.rollback();
} catch (Exception e1) {
}
}
return responseDTO;
}
}