I'm listening for connection changes through events pluging ("amq.rabbitmq.event", "connection.#").
It works properly so I'm adding at java side two additional parameters as clientproperties, to get the identity of the user that connects or disconnect.
However at c# side I can only access these properties as a list of byte[], and not sure on how to convert it to a Dictionary or so..
If I print all entries
if (args.BasicProperties.Headers.TryGetValue("client_properties", out object value))
{
var items = value as List<object>;
foreach(var item in items)
{
Console.WriteLine($"{item.GetType().ToString()}");
var bytes = item as byte[];
result.Add(Encoding.UTF8.GetString(bytes));
}
}
I can see this:
{<<"platform">>,longstr,<<"Java">>}
{<<"capabilities">>,table,[{<<"connection.blocked">>,bool,true},{<<"basic.nack">>,bool,true},{<<"exchange_exchange_bindings">>,bool,true},{<<"authentication_failure_close">>,bool,true},{<<"publisher_confirms">>,bool,true},{<<"consumer_cancel_notify">>,bool,true}]}
{<<"groupId">>,longstr,<<"1e6e935f0d4d9ec446d67dadc85cbafd10d1a095">>}
{<<"information">>,longstr,<<"Licensed under the MPL. See http://www.rabbitmq.com/">>}
{<<"version">>,longstr,<<"4.8.1">>}
{<<"copyright">>,longstr,<<"Copyright (c) 2007-2018 Pivotal Software, Inc.">>}
{<<"product">>,longstr,<<"RabbitMQ">>}
What kind of object format is and how can I parse this?:
{<<id>>,type,<<value>>}
Apparently ( as for an answer I got on Rabbit client google group for this questions ), client_properties is something that's not created to being read by the receiving party..
However is a really good way to have something like LWT ( Last Will and Testament ), then I am using it at the minute doing the parse by myself.
if (args.BasicProperties.Headers.TryGetValue("client_properties", out object value))
{
var items = value as List<object>;
foreach (var item in items)
{
var bytes = item as byte[];
//{<<id>>, type, <<value>>}
String itemStr = Encoding.UTF8.GetString(bytes);
var parts = itemStr.Split(",");
var key = CleanErlangString(parts[0]);
var value = CleanErlangString(parts[2]);
// Do things with key/value
}
}
ClearErlangFunction
private static string CleanErlangString(string toClean)
{
return toClean
.Replace("{", "").Replace("}", "")
.Replace("\"", "")
.Replace("<<", "").Replace(">>", "");
}
What I am doing to use it as LWT, is setting a custom property on client side and then obtaining it while reading events at "amq.rabbitmq.event", "connection.#". With that I know who have disconnected and even process something as LWT with my core server.
I hope this helps someone :)
Related
I work on university project in java. I have to download attachments from new emails using GMAIL API.
I successfully connected to gmail account using OAuth 2.0 authorization.
private static final List<String> SCOPES = Collections.singletonList(GmailScopes.GMAIL_READONLY);
I tried to get unseen mails using
ListMessagesResponse listMessageResponse = service.users().messages().list(user).setQ("is:unseen").execute();
listMessageResponse is not null but when I call method .getResultSizeEstimate() it returns 0
also I tried to convert listMessageResponse to List < Message > (I guess this is more usable) using
List<Message> list = listMessageResponse.getMessages();
But list launches NullPointerException
Then tried to get each attachment with
for(Message m : list) {
List<MessagePart> part = m.getPayload().getParts();
for(MessagePart p: part) {
if(p.getFilename()!=null && p.getFilename().length()>0) {
System.out.println(p.getFilename()); // Just to check attachment filename
}
}
}
Is my approach correct (if not how to fix it) and how should I download those attachments.
EDIT 1:
Fixed q parameter, I mistakenly wrote is:unseen instead of is:unread.
Now app reaches unread mails successfully.
(For example there was two unread mails and both successfully reached, I can get theirs IDs easy).
Now this part trows NullPointerException
List<MessagePart> part = m.getPayload().getParts();
Both messages have attachments and m is not null (I get ID with .getID())
Any ideas how to overcome this and download attachment?
EDIT 2:
Attachments Downloading part
for(MessagePart p : parts) {
if ((p.getFilename() != null && p.getFilename().length() > 0)) {
String filename = p.getFilename();
String attId = p.getBody().getAttachmentId();
MessagePartBody attachPart;
FileOutputStream fileOutFile = null;
try {
attachPart = service.users().messages().attachments().get("me", p.getPartId(), attId).execute();
byte[] fileByteArray = Base64.decodeBase64(attachPart.getData());
fileOutFile = new FileOutputStream(filename); // Or any other dir
fileOutFile.write(fileByteArray);
fileOutFile.close();
}catch (IOException e) {
System.out.println("IO Exception processing attachment: " + filename);
} finally {
if (fileOutFile != null) {
try {
fileOutFile.close();
} catch (IOException e) {
// probably doesn't matter
}
}
}
}
}
Downloading working like charm, tested app with different type of emails.
Only thing left is to change label of unread message (that was reached by app) to read. Any tips how to do it?
And one tiny question:
I want this app to fetch mails on every 10 minutes using TimerTask abstract class. Is there need for manual "closing" of connection with gmail or that's done automatically after run() method iteration ends?
#Override
public void run(){
// Some fancy code
service.close(); // Something like that if even exists
}
I don't think ListMessagesResponse ever becomes null. Even if there are no messages that match your query, at least resultSizeEstimate will get populated in the resulting response: see Users.messages: list > Response.
I think you are using the correct approach, just that there is no message that matches your query. Actually, I never saw is:unseen before. Did you mean is:unread instead?
Update:
When using Users.messages: list only the id and the threadId of each message is populated, so you cannot access the message payload. In order to get the full message resource, you have to use Users.messages: get instead, as you can see in the referenced link:
Note that each message resource contains only an id and a threadId. Additional message details can be fetched using the messages.get method.
So in this case, after getting the list of messages, you have to iterate through the list, and do the following for each message in the list:
Get the message id via m.getId().
Once you have retrieved the message id, use it to call Gmail.Users.Messages.Get and get the full message resource. The retrieved message should have all fields populated, including payload, and you should be able to access the corresponding attachments.
Code sample:
List<Message> list = listMessageResponse.getMessages();
for(Message m : list) {
Message message = service.users().messages().get(user, m.getId()).execute();
List<MessagePart> part = message.getPayload().getParts();
// Rest of code
}
Reference:
Class ListMessagesResponse
Users.messages: list > Response
I have integrated BIRT in web application.I am using Eclipse Luna,JDK 1.8, BIRT Report Engine 4.1.1 and Data source I am using is Excel Data Source(not JDBC and all that). From my JSP page I am passing two parameters in the URL using Javascript AJAX like:`
var reporturl ="/Reporting/loadReport?ReportName="+reportName+"&ReportFormat=html&Supplier=Supplier4&Metal=Gold&Metal=Tin";
$("#reportData").html("Loading...<br><img src='/Reporting/resources/images/loading.gif' align='middle' >");
$('#reportData').load(reporturl ,function(response, status, xhr) {
if (status == "error") {
var msg = "Sorry but there was an error getting details ! ";
$("#reportData").html(msg + xhr.status + " " + xhr.statusText);
}
});
For report parameter "Metal" I have selected Display type : List Box, Data Type : String and have selected Dynamic Values and then have checked "Allow Multiple Values" checkbox. Then in the Property Editor of table, in Filters tab I have given the expressions as follows:
row["Supplier Name"] Equal to params["Supplier"].value
row["Metal"] In params["Metal"].value
After this switching to JavaEE perspective in my ReportRenderer.java , I have the following code to get multiple values associated with the "Metal" parameter(which are passed from the URL), I have merged those values as a comma(,) seperated list in a single String variable like :
public static String getParameter( HttpServletRequest request,
String parameterName )
{
if ( request.getCharacterEncoding( ) == null )
{
try
{
request.setCharacterEncoding( UTF_8_ENCODE );
}
catch ( UnsupportedEncodingException e )
{
}
}
String[] values = request.getParameterValues(parameterName);
String temp="";
if(values.length>1)
{
int i=0;
for(i=0;i<values.length-1;i++)
{
temp=temp+values[i]+",";
}
temp=temp+values[i];
}
else
{
temp = values[0];
}
return temp;
}
In a HashMap I am getting all parameters and it's respective values successfully and have set that Map like:
HashMap<String,Object> tempMap = new HashMap<String,Object>();
tempMap = discoverAndSetParameters( runnable, request );
for(String str : tempMap.keySet())
{
System.out.println("Key : "+str);
System.out.println("Value : "+tempMap.get(str));
}
iRunTask.setParameterValues(tempMap);
Here runnable is the object of IReportRunnable and request is the object of HttpServletRequest.
Now when I am running the web application, after clicking on the hyperlink named "Reports" I am getting following exception on console and no output on web page.
org.eclipse.birt.report.engine.api.impl.ParameterValidationException: The type of parameter "Metal" is expected as "Object[]", not "java.lang.String".
at org.eclipse.birt.report.engine.api.impl.EngineTask.validateAbstractScalarParameter(EngineTask.java:857)
at org.eclipse.birt.report.engine.api.impl.EngineTask.access$0(EngineTask.java:789)
at org.eclipse.birt.report.engine.api.impl.EngineTask$ParameterValidationVisitor.visitScalarParameter(EngineTask.java:706)
at org.eclipse.birt.report.engine.api.impl.EngineTask$ParameterVisitor.visit(EngineTask.java:1531)
at org.eclipse.birt.report.engine.api.impl.EngineTask.doValidateParameters(EngineTask.java:692)
at org.eclipse.birt.report.engine.api.impl.RunTask.doRun(RunTask.java:214)
at org.eclipse.birt.report.engine.api.impl.RunTask.run(RunTask.java:86)
Please help me how to resolve this problem and again I am specifying I am using Excel Data Source not JDBC or Scripted and all that. I have already gone through many blogs where questions are related to JDBC data source and that didn't helped me.
When a listbox parameter is declared as "Allow multiple values", the BIRT engine is expecting an array of values, but in your case you send a String.
Therefore when you detect a multi-value parameter, instead of building a comma-separated String you should build a java array of values and pass this array to the parameter map. This way it will work.
Take care elements of this array should have the datatype expected by BIRT: if "Metal" parameter is set as "String" type in your report-design then you shoud be able to use "values" array as it is from getParameter function, otherwise it would be necessary to build a fresh array.
I have a requirement to fetch the SenderName,SenderEmail,ToNames,ToEmails,CCNames,CcEmails from a lotus notes document instance.
Issue1
Looking into lotus.domino.Document API I found out the method getItems. When I write the elements to the system.out values for SenderEmail, ToEmails and CcEmails can be found.
However values for SenderName(a.k.a From), ToNames cannot be derived that easily.
The values seems to be using an common name format. For example check check my system.output below.
Principal = "CN=Amaw Scritz/O=fictive"
$MessageID = "<OF0FF3779B.36590F8A-ON80257D15.001DBC47-65257D15.001DC804#LocalDomain>"
INetFrom = "AmawScritz#fictive.com"
Recipients = "CN=Girl1/O=fictive#fictive"
MailOptions = "0"
SaveOptions = "1"
From = "CN=Amaw Scritz/O=fictive"
AltFrom = "CN=Amaw Scritz/O=fictive"
SendTo = "CN=Girl1/O=fictive#fictive"
CopyTo = "CN=Girl2/O=fictive#fictive"
BlindCopyTo = ""
InetSendTo = "Girl1#fictive.com"
InetCopyTo = "Girl2#fictive.com"
$Abstract = "sasdasda"
$UpdatedBy = "CN=Amaw Scritz/O=fictive"
Body = "Hello World"
The question is how can I get 'Amaw Scritz' from the common name 'CN=Amaw Scritz/O=fictive'. Is there any look up mechanism that can be used. (I would prefer to have a option other than doing a substring of the common name)
Issue2
is it possible to retrieve SentTime and ReceivedTime from mail document instance?
I know that there are two methods called getCreated and getLastModified. getCreated can be loosely associated with the SentTime and getLastModified can be loosely associated with ReceivedTime. Are there are other ways to get times for SentTime and ReceivedTime.
Issue3
How can one distinguish whether a mail document is a Sent mail or a Received Mail?
Issue1
You can use Name class.
Here example from this link:
import lotus.domino.*;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
// (Your code goes here)
// Create a hierarchical name
Name nam = session.createName(
"CN=John B Goode/OU=Sales/OU=East/O=Acme/C=US");
// Returns:
// John B Goode
// John B Goode/Sales/East/Acme/US
// CN=John B Goode/OU=Sales/OU=East/O=Acme/C=US
System.out.println(nam.getCommon());
System.out.println(nam.getAbbreviated());
System.out.println(nam.getCanonical());
} catch(Exception e) {
e.printStackTrace();
}
}
}
Issue2
Use values of PostedDate field and DeliveredDate field of mail document.
Issue3
Check that $Inbox folder contains your mail document. Or take a look at Dave Delay answer.
I agree with #nempoBu4 on Issues 1 and 2. I disagree with the answer to Issue 3. A received message can be removed from the inbox, so checking $Inbox doesn't help you distinguish between sent and received messages.
Assuming you have the document open, the best approach is to check two items. Sent and received messages both have a PostedDate item, but only a received message has a DeliveredDate item. Incidentally, a draft message has neither PostedDate or DeliveredDate.
I tried to create a multiuserchat with Java. I'm using smack library.
Here is my code to create multiuserchat:
MultiUserChat muc = new MultiUserChat(connection, "roomname#somehost");
muc.create("mynickname");
Form form = muc.getConfigurationForm();
Form submitForm = form.createAnswerForm();
submitForm.setAnswer("muc#roomconfig_roomname", "A nice formatted Room Name");
submitForm.setAnswer("muc#roomconfig_roomdesc", "The description. It should be longer.");
muc.sendConfigurationForm(submitForm);
muc.addMessageListener(mucMessageListener); // mucMessageListener is a PacketListener
Then, I tried to capture the message sent by this room created above using mucMessageListener:
private PacketListener mucMessageListener = new PacketListener() {
public void processPacket(Packet packet) {
if (packet instanceof Message) {
Message message = (Message) packet;
// this is where I got the problem
}
}
}
As the message received by other part (the user who is not the owner of this multiuserchat), can he somehow get the value set in this line above:
submitForm.setAnswer("muc#roomconfig_roomname", "A nice formatted Room Name");
You see, getting just the JID of the room is not really good for the view. I expect I could have a String which value is "A nice formatted Room Name".
How can we get that?
You can easily get its configurations like name and etc from this code:
MultiUserChatManager mucManager = MultiUserChatManager.getInstanceFor(connection);
RoomInfo info = mucManager.getRoomInfo(room.getRoom());
now you can get its informations like this:
String mucName = info.getName();
Boolean isPersistence = info.isPersistent();
and etc.
Retrieving the value of muc#roomconfig_romname is described in XEP-45 6.4. Smack provides the MultiUserChat.getRoomInfo() method to perform the query.
RoomInfo roomInfo = MultiUserChat.getRoomInfo(connection, "roomname#somehost.com")
String roomDescription = roomInfo.getDescription()
If you want to read a value of var for example title name of room in config
Form form = chat.getConfigurationForm();
String value = form.getField("muc#roomconfig_roomname").getValues().next();
then do what ever you want with value..
I need to pass waypoints to google maps javascript directions api from ManagedBean to jsf page.
I'm trying to make JSONArray and pass it to jsf:
private JSONArray routesJSON;
with getters and setters.
Than im creating JSON : in loop im adding Strings with LatLang of waypoints to List<String>
routes.add("new google.maps.LatLng(" + o.getLatitude() + "," + o.getLongitude()+")");
And im getting JSON :
[{"location":"new google.maps.LatLng(50.495121,22.1705)"},{"location":"new google.maps.LatLng(50.57082,22.06813)"},{"location":"new google.maps.LatLng(50.570549,22.047871)"},{"location":"new google.maps.LatLng(50.521389,21.912695)"},{"location":"new google.maps.LatLng(50.495121,22.1705)"}]
from:
for()
array.put(obj);
}
System.out.println(array);
in JSF function for displaying route : (it works with hardcoded data)
function calcRoute() {
var waypts = [];
var start = new google.maps.LatLng(#{someBean.startLatitude}, #{someBean.startLongitude});
var end = new google.maps.LatLng(49.712112, 21.50667);
var way = #{someBean.routesJSON};
var request = {
origin:start,
destination:end,
optimizeWaypoints: true,
waypoints:way;
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(result);
}
});
}
But when im displaying that page map doesnt appear. I know it's probably because of " in JSON but i dont know how to remove it. Or may there are easiest ways to pass waypoint data from Bean to jsf page?
Instead of returning a JSON data packet that contains javascript statements like "new google.maps.LatLng(50.495121,22.1705)", it's more sensible to return just the coordinates.
So if you had a JSON packet that looks like this in your javascript (I don't know how to pass data between your Java and Javascript):
var routes = [
{"lat":"50.495121", "lng":"22.1705"},
{"lat":"50.57082", "lng":"22.06813"},
{"lat":"50.570549", "lng":"22.047871"},
{"lat":"50.521389", "lng":"21.912695"},
{"lat":"50.495121", "lng":"22.1705"}
]
You can turn this into an array like so:
var way = [];
for (var i = 0; i < routes.length; i++) {
way.push(new google.maps.LatLng(parseFloat(routes[i].lat), parseFloat(routes[i].lng)));
}
NB: the use of parseFloat to convert strings like "50.495121" into floating point numbers.