Not able to retrieve messages from topic using EMS.NET API - tibco-ems

I am trying to write a simple application to send messages to a topic from use input and show messages published on topic.
There are two command line executables - one for publisher and another for subscriber.
When I publish messages on a topic, I can see the messages getting submitted to the topic.
The following command shows that there are messages on the topic (see F1.gif):-
show stat EMS.Test.Topic
The following command shows that the messages are getting consumed by the subscribers (see F2.gif)
show stat consumers topic=EMS.Test.Topic
However, I am not able to retrieve messages the EMS .NET API. It gets stuck on Message msg = subscriber.Receive();. I made sure the connection details and authentication details are correct because they are used when publishing the messages.
public string ReceiveMessagesFromTopic(string topicName)
{
TopicConnection connection = null;
string messageFromPublisher = string.Empty;
try
{
var factory = new TIBCO.EMS.TopicConnectionFactory(serverUrl);
connection = factory.CreateTopicConnection(userName, password);
TopicSession session = connection.CreateTopicSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.CreateTopic(topicName);
TopicSubscriber subscriber = session.CreateSubscriber(topic);
connection.Start();
while (true)
{
Message msg = subscriber.Receive();
if (msg == null)
{
break;
}
if (msg is TextMessage)
{
TextMessage tm = (TextMessage) msg;
messageFromPublisher = tm.Text;
}
}
connection.Close();
}
catch (EMSException e)
{
if (connection!=null)
{
connection.Close();
}
throw;
}
return messageFromPublisher;
}

There was a silly mistake in my .NET code. the following while loop never returns so there is no return. I need to break the while loop when I get a message. Duh!!!!
while (true)
{
Message msg = subscriber.Receive();
if (msg == null)
{
break;
}
if (msg is TextMessage)
{
TextMessage tm = (TextMessage) msg;
messageFromPublisher = tm.Text;
break;
}
}

Related

netmq TryReceiveMultipartMessage() works abnormal

I used the netmq (VisualStudio 2022, by Nuget install netmq) as https://www.nuget.org/packages/NetMQ/ described.
One SubscriberSocket one thread to connect and receive message from one publisher. source code like below:
public void ZMQReceiveThread(string serverIP, int port)
{
//Create SubscriberSocket
SubscriberSocket subSocket = new SubscriberSocket();
//Connect to Publisher
subSocket.Connect("tcp://" + serverIP + ":" + port.ToString());
//Subscribe all topics
subSocket.Subscribe("");
//set timeout value
int timeout = 10000 * 300; //300ms
TimeSpan ts = new TimeSpan(timeout);
while (!_isStopEnabled)
{
NetMQMessage recvMessage = null;
bool bSuccess = subSocket.TryReceiveMultipartMessage(ts, ref recvMessage, 1);
if(bSuccess == true) //Recieve data successfully
{
//Handle the recvMessage
}
else //Timeout
{
//output log message
Loger.Error($"TryReceiveMultipartMessage({ts.TotalMilliseconds} ms) timeout...");
continue;
}
}
}
sometimes the subSocket.TryReceiveMultipartMessage() timeout although the publisher sent message continuously (we used another test app written in C language linked libzmq(https://github.com/zeromq/libzmq) which can receive the continuous message).
Any comments about this topic?
thanks a lot in advance.
I looked through the netmq source code(https://github.com/zeromq/netmq) but cannot find any clues about TryReceiveMultipartMessage()

Get Publish Response/PubAck latency with paho org.eclipse.paho.client.mqttv3.MqttClient publish

I am using paho library Classes for Mqtt Connections org.eclipse.paho.client.mqttv3.MqttClient. (not MqttAsyncClient)
In my case when I publish using
mqttClient.publish(uid + "/p", new MqttMessage(payload.toString().getBytes()));
This method does the task for me but doesn't return anything so I can't check the latency between publish and pubAck.
To get the latency I use the following instead of directly calling publish function of mqttClient.
public long publish(JsonObject payload , String uid, int qos) {
try {
MqttTopic topic = mqttClient.getTopic(uid + "/p");
MqttMessage message = new MqttMessage(payload.toString().getBytes());
message.setQos(qos);
message.setRetained(true);
long publishTime = System.currentTimeMillis();
MqttDeliveryToken token = topic.publish(message);
token.waitForCompletion(10000);
long pubCompleted = System.currentTimeMillis();
if (token.getResponse() != null && token.getResponse() instanceof MqttPubAck) {
return pubCompleted-publishTime;
}
return -1;
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
This gets the work done, but I am not sure whether this is the right approach or not. Please let me know in case there is some other way to to do this.

How to create an ad-hoc email and send it using Acumatica

In Acumatica you can use notifications to automate some emails.
In my scenario, we are creating a process that will at non-specific (non-set) times need to send an email when a specific condition is triggered, such as an employee needs to know they need to do something.
We are building this logic into the system and I am looking for a code sample of how to send the email when this happens.
We will be using an email template, but need to accomplish the feat in code.
I would hope there should be some kind of acumatica email class where we could just call it and pass the required info something like:
PX.Common.email.Send(params)...
Any example code would be appreciated.
It turns out that there is a KB article that gives an example of how to do this.
for our scenario, Here is a more recent version of the code that has been verified to send an email using either of 2 email templates.
private void mSendEmail(string toEmail, int? emailTemplateID, long? noteid, string source, string toDisplayName)
{
bool sent = false;
string sError = "Failed to send E-mail.";
POOrder porec = poOrder.Select(noteid);
EPExpenseClaim eprec = epExpense.Select(noteid);
try
{
Notification rowNotification = PXSelect<Notification,
Where<Notification.notificationID, Equal<Required<Notification.notificationID>>>>.Select(this, emailTemplateID);
if (rowNotification == null)
throw new PXException(PXMessages.Localize("Notification Template for Escalation is not specified."));
if (String.IsNullOrEmpty(toEmail))
throw new PXException(PXMessages.Localize("E-mail is not specified for Escalation Employee. Name=[" + toDisplayName +"]"));
if (source == "PO")
{
var sender = TemplateNotificationGenerator.Create(porec, rowNotification.NotificationID.Value);
sender.MailAccountId = rowNotification.NFrom.HasValue ?
rowNotification.NFrom.Value :
PX.Data.EP.MailAccountManager.DefaultMailAccountID;
sender.To = toEmail;
IEnumerable<EPActivity> epActivityArray = sender.Send();
if (epActivityArray.Count() > 0)
{ sent = true; }
}
if (source == "EP")
{
var sender = TemplateNotificationGenerator.Create(eprec, rowNotification.NotificationID.Value);
sender.MailAccountId = rowNotification.NFrom.HasValue ?
rowNotification.NFrom.Value :
PX.Data.EP.MailAccountManager.DefaultMailAccountID;
sender.To = toEmail;
IEnumerable<EPActivity> epActivityArray = sender.Send();
if (epActivityArray.Count() > 0)
{ sent = true; }
}
}
catch (Exception Err)
{
sent = false;
sError = Err.Message;
}
if (!sent)
throw new PXException(PXMessages.Localize(sError));
}
Here I want to present shorter version of sending email:
using PX.Objects.EP;
using PX.Data.EP;
**...**
var sender = new NotificationGenerator
{
To = "someone#example.com",
Subject = $"Subject information {DateTime.Now:d}",
Body = "Body of message",
BodyFormat = EmailFormatListAttribute.Text
};
sender.Send();

In NServiceBus full duplex application Server could not send/reply/return message

I have created a ASP.Net Web API project and using this link. NServiceBus is integrated with web api. Here is my configuration at web api as a client.
Configure.Serialization.Xml();
Configure.Transactions.Enable();
Configure.With()
.DefineEndpointName(Constants.ClientName)
.DefaultBuilder()
.ForWebApi()
.Log4Net()
.UseTransport<Msmq>()
.PurgeOnStartup(false)
.UnicastBus()
.ImpersonateSender(false)
.CreateBus()
.Start();
This is how I'm sending message to Server
var response = await Bus.Send(Constants.ServerName, request)
.Register<ResponseModel>((NServiceBus.CompletionResult completionResult) =>
{
ResponseModel responseMessage = null;
if (completionResult != null && completionResult.Messages.Length > 0)
{
var status = completionResult.Messages[0] as RequestStatus?;
if (status == RequestStatus.Successful)
{
responseMessage = TransactionManager.TransactionDictionary[request.RequestId].ResponseModel;
}
}
return responseMessage;
});
This is how I'm sending response from Server. I have commented some lines to show what I have already tried.
public void Handle(RequestModel message)
{
ProcessRequest(message).RunSynchronously();
}
private async Task ProcessRequest(RequestModel message)
{
....
ResponseModel response = new ResponseModel();
response.RequestId = message.RequestId;
response.Result = await responseMessage.Content.ReadAsStringAsync();
//Bus.Send(Util.Constants.ClientName, response);
//Bus.Reply(response);
//Bus.Reply<ResponseModel>((ResponseModel response) =>
//{
// response = Bus.CreateInstance<ResponseModel>(r =>
// {
// r.RequestId = message.RequestId;
// r.Result = responseMessage.Content.ReadAsStringAsync().Result;
// });
//});
await Bus.Send(Util.Constants.ClientName, response).Register((NServiceBus.CompletionResult completionResult) =>
{
if (completionResult != null && completionResult.Messages.Length > 0)
{
var msg = completionResult.Messages[0];
if (msg != null)
{
var status = (RequestStatus)msg;
return status;
}
}
return RequestStatus.Error;
});
....
}
From any of the above response methods ultimately all messages end up in error queue.
Previously I was getting 'Could not enlist message' error. Now it is not throwing that error. But Server could not send message to Client.
I could not get what I'm doing wrong. Please also suggest if you see any scope for improvements.
I'm not sure if TransactionScope work correctly with async/await in C#. According to this question (Get TransactionScope to work with async / await) in .NET 4.5.1 there was introduced option for TransactionScope that enable mixing it with async/await. Unfortunately NServiceBus doesn't support .NET 4.5/4.5.1 so try just remove async/await.

Grails Issue Dealing With Tcp Client & Tcp Server

I created a Tcp Client & Tcp Server in Groovy awhile back and had no issues with it. I was only connecting to one machine at the time to gather data. This time I am attempting to connect to the script on multiple hosts and it is only saving one of the hosts information in my grails app.
My Grails application is simple, it has a domain class for Machines (basically the computers and the information on them that I seek) and it will use my TcpClient.groovy script to connect and gather information from the TcpServer.groovy on the other computers. For each host, it should save the information gathered, however, it seems to skip right over saving any host aside from the last one.
Tcp Client :
//TCP CLIENT
public void queryData(def hosts) {
for(int aHost = 0; aHost < hosts.size; aHost++) {
cristalClient(hosts[aHost]);
}
}
public void cristalClient(String host) {
commands = ["dateScan", "computerName", "ip", "quit"]
answers = [commands.size]
requestSocket = new Socket(host, 2000)
r = new BufferedReader(new InputStreamReader(requestSocket.getInputStream()));
w = new BufferedWriter(new OutputStreamWriter(requestSocket.getOutputStream()));
String message = "Connection was successful"
message = readAvailable(r)
println("Sever>" + message)
for(int n = 0; n < commands.size; n++) {
sendMessage(commands[n]);
answers[n] = readAvailable(r)
}
lastRead = answers[0]
machineName = answers[1]
ipAddress = answers[3]
w.flush()
w.close()
}
public String readAvailable(r) {
String out = ""
String dum = null
while((dum = r.readLine()) !=null) {
if(dum == ">>EOF<<") return out
if(out.length() > 0) out += "\r\n"
out += dum
}
return out
}
public void sendMessage(msg) {
w.write(msg+"\r\n");
w.flush();
println("Client>" + msg);
}
public void printData(abc) {
abc.eachWithIndex { it, index ->
println "Drive $index"
it.each { k, v ->
println "\t$k = $v"
}
}
}
Tcp Server :
//TCP Server
def server = new ServerSocket(2000)
println("Waiting for connection")
server.accept() { socket ->
socket.withStreams { input, output ->
w = new BufferedWriter(new OutputStreamWriter(output))
String message = "Connection was successful"
r = new BufferedReader(new InputStreamReader(input))
while(true) {
if(message != null) {
sendMessage(message)
message = null
}
String a = r.readLine()
if(a == "dateScan") {
message = new Date
} else if(a == "computerName") {
message = InetAddress.getLocalHost().hostName
} else if(a == "ip") {
message = InetAddress.getLocalHost().getHostAddress()
} else if(a == "quit") {
server.close()
return
} else {
message = "$a command unknown."
println message
}
}
}
}
def sendMessage(String msg) {
println( "sending: >" + msg + "<" )
w.writeLine(msg)
w.writeLine(">>EOF<<")
w.flush();
}
Grails Controller :
//Grails Controller
CollectMachines {
def w = new tcpClient()
def hosts = ["winXp", "Win7"]
w.queryData(hosts)
def abc = w.hardDrive
abc.each { println it }
int numberOfDrives = abc.size()
//add new machine
numberOfDrives.times {
def machineName = abc.computerName[it]
def machineInstance = Machine.findByMachineName(machineName)
if (!machineInstance) {
machineInstance = new Machine(machineName)
}
def lastScan = abc.lastScan[it]
def scanDate = new Date().parse("E MMM dd H:m:s z yyyy", lastScan)
def ipAddress = abc.ipAddress[it]
machineInstance.setIpAddress(ipAddress)
machineInstance.setDateScanned(scanDate)
machineInstance.save()
}
redirect(action: "list")
}
Do I need to put a pause in so that the server has time to send a response? My Tcp Client does send out all the commands but only gets responses for the last set of commands.
Also, sorry for the indentation issues with my code snippets, I'm not sure why they are messed up.
.
There are a few problems with your code. tcpClient never assigns to hardDrive, for example. Assuming this is an oversight, I think the real problem is that tcpClient is querying data for multiple hosts, and storing all the results in the same instance variables answers, and ultimately lastRead, machineName, and ipAddress.
You need to store the results for each host separately. One way would be to have answers be a map of lists. For example, answers[host][0] would be the first answer for a given host.
I don't think any kind of pause is necessary.

Resources