From the url
https://javamail.java.net/nonav/docs/api/com/sun/mail/pop3/package-summary.html,
You can also pre-fetch all the UIDs for all messages like this:
FetchProfile fp = new FetchProfile();
fp.add(UIDFolder.FetchProfileItem.UID);
folder.fetch(folder.getMessages(), fp);
Then use the technique above to get the UID for each message. This is similar to the technique used with the UIDFolder interface supported by IMAP, but note that POP3 UIDs are strings, not integers like IMAP UIDs. See the POP3 spec for details.
From this, https://www.ietf.org/rfc/rfc1939.txt,
In number 7, there's an example of what I need.
Examples:
S: +OK POP3 server ready <1896.697170952#dbc.mtview.ca.us>
C: APOP mrose c4c9334bac560ecc979e58001b3e22fb
S: +OK maildrop has 1 message (369 octets)
In this example, the shared secret is the string `tan-
staaf'. Hence, the MD5 algorithm is applied to the string
<1896.697170952#dbc.mtview.ca.us>tanstaaf
which produces a digest value of
c4c9334bac560ecc979e58001b3e22fb //this is what we need in Java
After this, how do we get the MessageID / UID of each message?
Sample Message ID that I need. A fuego.mail Library that was deprecated was providing us this before:
<F855F5879C6E754E9DE37F2E7D0762327C942B43#GADC-EMB099.ap.abc.com>
UPDATE
I got a 3 digit integer i.e. 561 when using this
Store store = emailSession.getStore(MAILSTORETYPE);
store.connect(HOST, USERNAME, PASSWORD);
Folder emailFolder = store.getFolder("INBOX");
emailFolder.open(Folder.READ_ONLY);
FetchProfile fp = new FetchProfile();
fp.add(UIDFolder.FetchProfileItem.UID);
emailFolder.fetch(emailFolder.getMessages(), fp);
POP3Folder pf =(POP3Folder)emailFolder;
Message[] messages = emailFolder.getMessages();
for (int i = 0, n = messages.length; i < n; i++) {
Message message = messages[i];
String uid = pf.getUID(message);
System.out.println(uid);
Related
currently I'm creating an email service for my hobby project for newly signed up users. This is the relevant part of the code, which causes me some headache:
private Message createEmail(String firstName, String password, String email) throws MessagingException {
Message message = new MimeMessage(getEmailSession());
message.setFrom(new InternetAddress(FROM_EMAIL));
message.setRecipient(Message.RecipientType.TO, InternetAddress.parse(email, false)[0]);
message.setRecipient(Message.RecipientType.CC, InternetAddress.parse(CC_EMAIL, false)[0]);
message.setSubject(EMAIL_SUBJECT);
message.setText("Hello " + firstName + ", \n \n Your new account password is: " + password + "\n \n " +
"The support team");
message.setSentDate(new Date());
message.saveChanges();
return message;
}
I have two problems with this line message.setRecipient(Message.RecipientType.TO, InternetAddress.parse(email, false)[0]); (and of course the same problem with the next line below it):
On the internet, if I google after it, everywhere it is used like this:
message.setRecipient(Message.RecipientType.TO, InternetAddress.parse(email, false);
so, without the indexing. But if I remove the indexing, I get an IDE error, which says, that the function requires a type of Address, but it has got InternetAddress[], an array. That's why I put the indexing.
But if I leave the indexing and run the app and register a new user, I get the error in the console: Index 0 out of bounds for length 0. Obviously, the InternetAddress[] array is empty. But why?
What exactly is going on here?
Looking at the docs, it should be new InternetAddress(String, boolean), which
Parse[s] the given string and create[s] an InternetAddress.
instead of InternetAddress.parse(String, boolean), which
Parse[s] the given sequence of addresses into InternetAddress objects.
I need to create a REST service in the Java programming language that receives JMS connection factory's JNDI name and JMS topic's JNDI name as input and should return the number of messages in the resource at the moment.
The problem is getting the length of the topic from IBM WAS.
I know about the existence of TopicBrowser from Oracle, with which you can get all the messages in the topic and just count their number. But for some reason, we do not use it.
My idea is to get the SIB Destination queue length property, which is located in:
Buses> Bus> Recipients> MyTopic.Space> Publication Points, in the web console.
I use:
IBM WAS 9.0. ND.
Default Message Provider.
I will be glad to any advice.
You can get the state of a subscriber using the admin client for example:
// Start by querying the objectName of the Publication Point (Topic Space on a specific node).
AdminClient adminClient = AdminClientFactory.createAdminClient(connectProps);
StringBuffer oNameQuery= new StringBuffer();
oNameQuery.append(adminClient.getDomainName()).append(":*");
oNameQuery.append(",type=").append("SIBPublicationPoint");
oNameQuery.append(",name=").append("Default.Topic.Space");
oNameQuery.append(",node=").append(nodeName);
oNameQuery.append(",process=").append("server1");
oSet= adminClient.queryNames(new ObjectName(oNameQuery.toString()), null);
ObjectName defaultTopicSpaceOn = (ObjectName) oSet.iterator().next();
System.out.println("Default.Topic.Space ObjectName:"+defaultTopicSpaceOn);
// Then look at each subscription storing messages in the Publication Point.
Long depth = (Long) adminClient.invoke (defaultTopicSpaceOn, "getDepth", null, null);
System.out.println("DefaultTopicSpace Depth:"+depth+"\n");
SIBSubscription[] subscriptions = (SIBSubscription[]) adminClient.invoke (defaultTopicSpaceOn, "getSubscriptions", null, null);
for (SIBSubscription subscription : subscriptions) {
System.out.print("DefaultTopicSpace Subscription:"+subscription.getName()
+" Id:"+subscription.getId()
+" SubscriberId:"+subscription.getSubscriberId()
+" Selector:"+subscription.getSelector()
+" Depth:"+subscription.getDepth());
for (String topicName: subscription.getTopics())
System.out.print(" Topic:"+topicName);
System.out.println();
}
This produces something like:
DefaultTopicSpace Depth:2
DefaultTopicSpace Subscription:Default.Topic.Space Id:21974964F5B726A6C21C7E59 SubscriberId:jmsThinClient.JMSSendReceiveclientID##jmsThinClient.JMSSendReceiveSubscription Selector:null Depth:2 Topic:Topic1/*
Api doc:https://www.ibm.com/support/knowledgecenter/SSEQTP_8.5.5/com.ibm.websphere.javadoc.doc/web/apidocs/com/ibm/websphere/sib/admin/package-summary.html
I'm not familiar to JSON and not sure if this is possible,
Background:
I'm using AWS cloudwatch and uses AWS SNS to send a HTTPS Endpoint which is Twilio. Notification are Good, Working as Expected in Hipchat, It was concise and summarize
[ALARM] saas-ajtest-mem-gt-80-5min Threshold Crossed: 2 datapoints [47.9 (07/08/17 01:10:00), 47.9 (07/08/17 01:05:00)] were greater than or equal to the threshold (30.0).
but when it was sent to my Twilio number, I will receive all the message way too long.
Type: "Notification"
MessageId" : "27684767-bf13-5e0f-b02d-15667f98e595"
TopicArn: "arn:aws:sns:us-east-1:00000000:critical_twilio"
Subject: "ALARM: "saas-ajtest-mem-gt-80-5min" in US East (N. Virginia)"
Message: {"AlarmName":"saas-ajtest-mem-gt-80-5min""AlarmDescription":null"AWSAccountId":"00000000""NewStateValue":"ALARM""NewStateReason":"Threshold Crossed: 2 datapoints [47.9 (07/08/17 01:10:00) 47.9 (07/08/17 01:05:00)] were greater than or equal to the threshold (30.0).""StateChangeTime":"2017-08-07T01:11:39.708+0000""Region":"US East (N. Virginia)""OldStateValue":"OK""Trigger":{"MetricName":"MemoryUtilization""Namespace":"test""StatisticType":"Statistic""Statistic":"AVERAGE""Unit":null"Dimensions":[{"name":"ContainerName""value":"ajtest"}]"Period":60"EvaluationPeriods":5"ComparisonOperator":"GreaterThanOrEqualToThreshold""Threshold":30.0"TreatMissingData":"""EvaluateLowSampleCountPercentile":""}}"
What I want to do is to Get only the AlarmName, Threshold Crossed,Dimensions name. Basically I want a output similar to the hipchat.
This my sample groovy script
def slurper = new groovy.json.JsonSlurper()
def result = slurper.parseText( body )
def type = result.Type
def messageID = result.MessageId
def subject = result.Subject
def message = result.Message
def alldata = type + messageID + subject + message
Tried using
def message = result.Message.AlarmName
def message = result.Message."AlarmName"
But it will return null only.
Any Inputs will be appreciated. Thanking you ahead of time :)
Actually found a solution, I've used map
Map<String, String> mappedResult = (Map<String, String>) slurper.parseText( message )
This will get the other json :)
My client wants to control the HVAC systems installed in their site with a custom solution. The HVAC devices provide MODBUS TCP/IP connectivity. I'm new to this field and have no knowledge of MODBUS. I searched the internet and found jamod as a java library for MODBUS. Now I would like to write a program using jamod. But my confusion is how do I get the address of the device I want to connect. And my second problem is even if I manage to connect the device , how can I get required data (in engineering units like temperature) from MODBUS. My questions may sound awful but please forgive me as I'm a novice in this field.
How do I get the address of the device I want to connect to?
This kind of depends on if you're connecting over Modbus RTU or Modbus TCP. RTU (serial) will have a slave id you'll specify while tcp is more direct and the slave id should always be 1.
How can I get required data (in engineering units like temperature) from MODBUS?
Hopefully the data is already formatted in engineering units. Check the device's manual and there should be a table or chart mapping registers to values.
Example:
String portname = "COM1"; //the name of the serial port to be used
int unitid = 1; //the unit identifier we will be talking to, see the first question
int ref = 0; //the reference, where to start reading from
int count = 0; //the count of IR's to read
int repeat = 1; //a loop for repeating the transaction
// setup the modbus master
ModbusCoupler.createModbusCoupler(null);
ModbusCoupler.getReference().setUnitID(1); <-- this is the master id and it doesn't really matter
// setup serial parameters
SerialParameters params = new SerialParameters();
params.setPortName(portname);
params.setBaudRate(9600);
params.setDatabits(8);
params.setParity("None");
params.setStopbits(1);
params.setEncoding("ascii");
params.setEcho(false);
// open the connection
con = new SerialConnection(params);
con.open();
// prepare a request
req = new ReadInputRegistersRequest(ref, count);
req.setUnitID(unitid); // <-- remember, this is the slave id from the first connection
req.setHeadless();
// prepare a transaction
trans = new ModbusSerialTransaction(con);
trans.setRequest(req);
// execute the transaction repeat times because serial connections arn't exactly trustworthy...
int k = 0;
do {
trans.execute();
res = (ReadInputRegistersResponse) trans.getResponse();
for (int n = 0; n < res.getWordCount(); n++) {
System.out.println("Word " + n + "=" + res.getRegisterValue(n));
}
k++;
} while (k < repeat);
// close the connection
con.close();
First, "address" is ambiguous when you're working with Modbus/TCP since there is the IP address of the slave, the unit number of the thing you're talking to (typically 0 for Modbus/TCP), and the address of any registers.
For the "engineering units" question, what you're going to want is the Modbus register map, with any units or conversion factors included. You may also need to know data types, since all Modbus registers are 16 bits.
I have multiple messages in SQS. The following code always returns only one, even if there are dozens visible (not in flight). setMaxNumberOfMessages I thought would allow multiple to be consumed at once .. have i misunderstood this?
CreateQueueRequest createQueueRequest = new CreateQueueRequest().withQueueName(queueName);
String queueUrl = sqs.createQueue(createQueueRequest).getQueueUrl();
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl);
receiveMessageRequest.setMaxNumberOfMessages(10);
List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages();
for (Message message : messages) {
// i'm a message from SQS
}
I've also tried using withMaxNumberOfMessages without any such luck:
receiveMessageRequest.withMaxNumberOfMessages(10);
How do I know there are messages in the queue? More than 1?
Set<String> attrs = new HashSet<String>();
attrs.add("ApproximateNumberOfMessages");
CreateQueueRequest createQueueRequest = new CreateQueueRequest().withQueueName(queueName);
GetQueueAttributesRequest a = new GetQueueAttributesRequest().withQueueUrl(sqs.createQueue(createQueueRequest).getQueueUrl()).withAttributeNames(attrs);
Map<String,String> result = sqs.getQueueAttributes(a).getAttributes();
int num = Integer.parseInt(result.get("ApproximateNumberOfMessages"));
The above always is run prior and gives me an int that is >1
Thanks for your input
AWS API Reference Guide: Query/QueryReceiveMessage
Due to the distributed nature of the queue, a weighted random set of machines is sampled on a ReceiveMessage call. That means only the messages on the sampled machines are returned. If the number of messages in the queue is small (less than 1000), it is likely you will get fewer messages than you requested per ReceiveMessage call. If the number of messages in the queue is extremely small, you might not receive any messages in a particular ReceiveMessage response; in which case you should repeat the request.
and
MaxNumberOfMessages: Maximum number of messages to return. SQS never returns more messages than this value but might return fewer.
There is a comprehensive explanation for this (arguably rather idiosyncratic) behaviour in the SQS reference documentation.
SQS stores copies of messages on multiple servers and receive message requests are made to these servers with one of two possible strategies,
Short Polling : The default behaviour, only a subset of the servers (based on a weighted random distribution) are queried.
Long Polling : Enabled by setting the WaitTimeSeconds attribute to a non-zero value, all of the servers are queried.
In practice, for my limited tests, I always seem to get one message with short polling just as you did.
I had the same problem. What is your Receive Message Wait Time for your queue set to? When mine was at 0, it only returned 1 message even if there were 8 in the queue. When I increased the Receive Message Wait Time, then I got all of them. Seems kind of buggy to me.
I was just trying the same and with the help of these two attributes setMaxNumberOfMessages and setWaitTimeSeconds i was able to get 10 messages.
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(myQueueUrl);
receiveMessageRequest.setMaxNumberOfMessages(10);
receiveMessageRequest.setWaitTimeSeconds(20);
Snapshot of o/p:
Receiving messages from TestQueue.
Number of messages:10
Message
MessageId: 31a7c669-1f0c-4bf1-b18b-c7fa31f4e82d
...
receiveMessageRequest.withMaxNumberOfMessages(10);
Just to be clear, the more practical use of this would be to add to your constructor like this:
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl).withMaxNumberOfMessages(10);
Otherwise, you might as well just do:
receiveMessageRequest.setMaxNumberOfMessages(10);
That being said, changing this won't help the original problem.
Thanks Caoilte!
I faced this issue also. Finally solved by using long polling follow the configuration here:
https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-long-polling-for-queue.html
Unfortunately, to use long polling, you must create your queue as FIFO one. I tried standard queue with no luck.
And when receiving, need also set MaxNumberOfMessages. So my code is like:
ReceiveMessageRequest receive_request = new ReceiveMessageRequest()
.withQueueUrl(QUEUE_URL)
.withWaitTimeSeconds(20)
.withMaxNumberOfMessages(10);
Although solved, still feel too wired. AWS should definitely provide a more neat API for this kind of basic receiving operation.
From my point, AWS has many many cool features but not good APIs. Like those guys are rushing out all the time.
For small task list I use FIFO queue like stackoverflow.com/a/55149351/13678017
for example modified AWS tutorial
// Create a queue.
System.out.println("Creating a new Amazon SQS FIFO queue called " + "MyFifoQueue.fifo.\n");
final Map<String, String> attributes = new HashMap<>();
// A FIFO queue must have the FifoQueue attribute set to true.
attributes.put("FifoQueue", "true");
/*
* If the user doesn't provide a MessageDeduplicationId, generate a
* MessageDeduplicationId based on the content.
*/
attributes.put("ContentBasedDeduplication", "true");
// The FIFO queue name must end with the .fifo suffix.
final CreateQueueRequest createQueueRequest = new CreateQueueRequest("MyFifoQueue4.fifo")
.withAttributes(attributes);
final String myQueueUrl = sqs.createQueue(createQueueRequest).getQueueUrl();
// List all queues.
System.out.println("Listing all queues in your account.\n");
for (final String queueUrl : sqs.listQueues().getQueueUrls()) {
System.out.println(" QueueUrl: " + queueUrl);
}
System.out.println();
// Send a message.
System.out.println("Sending a message to MyQueue.\n");
for (int i = 0; i < 4; i++) {
var request = new SendMessageRequest()
.withQueueUrl(myQueueUrl)
.withMessageBody("message " + i)
.withMessageGroupId("userId1");
;
sqs.sendMessage(request);
}
for (int i = 0; i < 6; i++) {
var request = new SendMessageRequest()
.withQueueUrl(myQueueUrl)
.withMessageBody("message " + i)
.withMessageGroupId("userId2");
;
sqs.sendMessage(request);
}
// Receive messages.
System.out.println("Receiving messages from MyQueue.\n");
var receiveMessageRequest = new ReceiveMessageRequest(myQueueUrl);
receiveMessageRequest.setMaxNumberOfMessages(10);
receiveMessageRequest.setWaitTimeSeconds(20);
// what receive?
receiveMessageRequest.withMessageAttributeNames("userId2");
final List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages();
for (final Message message : messages) {
System.out.println("Message");
System.out.println(" MessageId: "
+ message.getMessageId());
System.out.println(" ReceiptHandle: "
+ message.getReceiptHandle());
System.out.println(" MD5OfBody: "
+ message.getMD5OfBody());
System.out.println(" Body: "
+ message.getBody());
for (final Entry<String, String> entry : message.getAttributes()
.entrySet()) {
System.out.println("Attribute");
System.out.println(" Name: " + entry
.getKey());
System.out.println(" Value: " + entry
.getValue());
}
}
Here's a workaround, you can call receiveMessageFromSQS method asynchronously.
bulkReceiveFromSQS (queueUrl, totalMessages, asyncLimit, batchSize, visibilityTimeout, waitTime, callback) {
batchSize = Math.min(batchSize, 10);
let self = this,
noOfIterations = Math.ceil(totalMessages / batchSize);
async.timesLimit(noOfIterations, asyncLimit, function(n, next) {
self.receiveMessageFromSQS(queueUrl, batchSize, visibilityTimeout, waitTime,
function(err, result) {
if (err) {
return next(err);
}
return next(null, _.get(result, 'Messages'));
});
}, function (err, listOfMessages) {
if (err) {
return callback(err);
}
listOfMessages = _.flatten(listOfMessages).filter(Boolean);
return callback(null, listOfMessages);
});
}
It will return you an array with a given number of messages