Smack Roster Entries are null - javafx

I am creating a java fx application for openfire chat client.
i am using smack 4.1 rc1 to connect to the server.
i am able to to connect to server send presence information to others and send messages to other users as well.
however i am not able to iterate through the roster.
when i get roster object and debug it its shows a hash map of 3 roster entries that means the roster is getting loaded in roster object. however when i use roster.getentries method to store it into the Collection of roster entries it shows 0 object. even the roster.getentriescount() method returns 0 though i can see the roster user names in the debug view
try {
config = XMPPTCPConnectionConfiguration.builder()
.setUsernameAndPassword(mUserName+ "#" + Domain, mPassword)
.setServiceName(HostName)
.setHost(HostName)
.setPort(PortName)
.setResource(Resource)
.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
.build();
mXmppConnection = new XMPPTCPConnection(config);
mXmppConnection.connect();
mXmppConnection.login();
// Presence presence=new Presence();
Presence presence ;
if(mPresence) presence = new Presence(Presence.Type.available);
else presence = new Presence(Presence.Type.unavailable);
presence.setStatus("On Smack");
XMPPConnection conn=(XMPPConnection) mXmppConnection;
Chat chat = ChatManager.getInstanceFor(mXmppConnection).createChat
("monika#ipaddress");
chat.sendMessage("Howdy from smack!");
// Send the packet (assume we have a XMPPConnection instance called "con").
mXmppConnection.sendPacket(presence);
System.out.println("Connected successfully");
Roster roster = Roster.getInstanceFor(conn);
Collection<RosterEntry> entries = roster.getEntries();
int i=0;
for (RosterEntry entry : entries) {
System.out.println(entry);
i++;
}
System.out.println("Rosters Count - "+ i+ roster.getEntryCount());
has any one encountered the same problem before?

You may have to check if roster is loaded before calling getEntries.
Roster roster = Roster.getInstanceFor(connection);
if (!roster.isLoaded())
roster.reloadAndWait();
Collection <RosterEntry> entries = roster.getEntries();

thanks for Deepak Azad
Here full code
public void getRoaster(final Callback<Collection<RosterEntry>> callback) {
final Roster roster = Roster.getInstanceFor(connection);
if (!roster.isLoaded())
try {
roster.reloadAndWait();
} catch (SmackException.NotLoggedInException | SmackException.NotConnectedException | InterruptedException e) {
e.printStackTrace();
}
Collection<RosterEntry> entries = roster.getEntries();
for (RosterEntry entry : entries) {
android.util.Log.d(AppConstant.PUBLIC_TAG, entry.getName());
}
}

I have just solved this problem. I'm using OpenFire as XMPP server. I checked the field "Subscription" in the users in roster and it was "None". After change it by "Both", it worked, and entries are being fetched.
Hope it helps!

Related

Inconsistent results when listing groups an external account belongs to

Our Google domain has groups (synced copies of our Active Directory email listservs/distribution groups) that have a lot of external accounts (currently kept as contacts in Active Directory).
As part of an intranet site I'm building I'm trying to be able to do mass search and replace of individual contact email address when for example a school district changes its domain name. One of the visual/verification steps I'm working on is to list the Google group membership of any selected external account, but I'm getting mixed results. For some accounts it seems to list the groups properly, and for others it doesn't seem to pull any. I have verified the external account's group membership in both Active Directory and in Google Admin group management, but when I query Google via code I don't get valid results every time... What am I missing? Code below.
-- in Global.asax
public static List<string> GOOGLE_GetListOfUsersGroups(string useremail)
{
List<string> groupList = new List<string>();
try
{
///stripped out credential/service stuff...
var groups = service.Groups.List();
groups.UserKey = useremail;
Groups gs = groups.Execute();
if (gs != null)
{
foreach (Google.Apis.Admin.Directory.directory_v1.Data.Group g in gs.GroupsValue)
groupList.Add(g.Email);
}
}
catch (Exception ex)
{
SendERROREmail("GLOBAL<HR>GOOGLE_GetListOfUsersGroups()<HR>useremail:" + useremail + "<HR>" + ex.ToString());
}
return groupList;
}
and the consuming function:
--- in Page.aspx
protected void ddlADExternalContacts_SelectedIndexChanged(object sender, EventArgs e)
{
lbContactsGoogleGroups.Items.Clear();
if (ddlADExternalContacts.SelectedIndex > 0)
{
//show what google has for same group
List<string> memberList = Global.GOOGLE_GetListOfUsersGroups(ddlADExternalContacts.SelectedValue);
if (memberList != null)
{
foreach (string s in memberList)
lbContactsGoogleGroups.Items.Add(new ListItem(s, s));
}
}
}
Also, does anyone have a good example how to handle this in Google's 'preferred' JSON format rather then the API route?
UPDATE: Ok, its not my code, its something with the group/Google. When I use the 'try it' functionality on the sdk admin site I get the same results for groups that work (in my code and their site) and no results from the same groups that should be showing results...
{
"kind": "admin#directory#groups",
"etag": "\"HKdfSgTnCxrWl3RtRnlZSCPY3NjdWJxz53nrhwSz7ob4/oMWMqbsluP5m2PCo8Y7WmWeHGP4\""
}
Not that that helps me any, as there's no error or anything, just the 'no groups' result as if it can't find the external account...
UPDATE2: Ok, based on what I'm seeing after some testing, I have a sneaky suspicion that Google is doing some validation of emails before checking for group membership and reporting anything. I.E. if the email being searched for is no longer valid (client's server doesn't responds that the account is reachable/enabled/exists...), it won't bother going any further... will try it out with a few more email addresses that I know should be invalid and update....later.
It looks like what you are experiencing might be a bug.
This has been reported on Google Issue Tracker here.
What you can do in this situation is to star the issue above and eventually add a comment saying that you are affected by it.

Exchange Web Services find item by unique id

I just started using Microsoft Exchange Web Services for the first time. Want I want to be able to do is the following:
Create Meeting
Update Meeting
Cancel/Delete Meeting
These meetings are created in an ASP.NET MVC application and saved into a SQL Server database. I simply wish to integrate this with the on site Exchange Server. So far, I'm able to created my meeting with the following code:
public static Task<string> CreateMeetingAsync(string from, List<string> to, string subject, string body, string location, DateTime begin, DateTime end)
{
var tcs = new TaskCompletionSource<string>();
try
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.Credentials = CredentialCache.DefaultNetworkCredentials;
//service.UseDefaultCredentials = true;
// I suspect the Service URL needs to be set from the user email address because this is then used to set the organiser
// of the appointment constructed below. The Organizer is a read-only field that cannot be manually set. (security measure)
service.AutodiscoverUrl(from);
//service.Url = new Uri(WebConfigurationManager.AppSettings["ExchangeServer"]);
Appointment meeting = new Appointment(service);
meeting.Subject = subject;
meeting.Body = "<span style=\"font-family:'Century Gothic'\" >" + body + "</span><br/><br/><br/>";
meeting.Body.BodyType = BodyType.HTML;
meeting.Start = begin;
meeting.End = end;
meeting.Location = location;
meeting.ReminderMinutesBeforeStart = 60;
foreach (string attendee in to)
{
meeting.RequiredAttendees.Add(attendee);
}
meeting.Save(SendInvitationsMode.SendToAllAndSaveCopy);
tcs.TrySetResult(meeting.Id.UniqueId);
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
return tcs.Task;
}
This successfully creates my meeting, places it into the user's calendar in outlook and sends a meeting request to all attendees. I noticed the following exception when attempting to call meeting.Save(SendInvitationsMode.SendToAllAndSaveCopy); twice:
This operation can't be performed because this service object already has an ID. To update this service object, use the Update() method instead.
I thought: Great, it saves the item in exchange with a unique id. I'll save this ID in my application's database and use it later to edit/cancel the meeting. That is why I return the id: tcs.TrySetResult(meeting.Id.UniqueId);
This is saved nicely into my application's database:
Now, I am attempting to do the next part where I update the meeting, but I cannot find a way to search for the item based on the unique identifier that I'm saving. An example I found on code.msdn uses the service.FindItems() method with a query that searches the subject:
string querystring = "Subject:Lunch";
FindItemsResults<Item> results = service.FindItems(WellKnownFolderName.Calendar, querystring, view);
I don't like this. There could be a chance that the user created a meeting outside of my application that coincidentally has the same subject, and here come's my application and cancel's it. I tried to determine wether it's possible to use the unique id in the query string, but this does not seem possible.
I did notice on the above query string page that the last property you can search on is (property is not specified) that searches in "all word phase properties.". I tried thus simply putting the id into the query, but this returns no results:
FindItemsResults<Item> results = service.FindItems(WellKnownFolderName.Calendar, "AAMkADJhZDQzZWFmLWYxYTktNGI1Yi1iZTA5LWVmOTE3MmJiMGIxZgBGAAAAAAAqhOzrXRdvRoA6yPu9S/XnBwDXvBDBMebkTqUWix3HxZrnAAAA2LKLAAB5iS34oLxkSJIUht/+h9J1AAFlEVLAAAA=", view);
Use the Appointment.Bind static function, providing a service object and the ItemId saved in your database. Be aware with meeting workflow (invite, accept, reject) can re-create a meeting on the same calendar with a new ItemId. But if you are just looking at the meeting you make on your own calendar, you should be OK.

WCF Transaction with multiple inserts

When creating a user, entries are required in multiple tables. I am trying to create a transaction that creates a new entry into one table and then pass the new entityid into the parent table and so on. The error I am getting is
The transaction manager has disabled its support for remote/network
transactions. (Exception from HRESULT: 0x8004D024)
I believe this is caused by creating multiple connections within a single TransactionScope, but I am unsure on what the best/most efficient way of doing this is.
[OperationBehavior(TransactionScopeRequired = true)]
public int CreateUser(CreateUserData createData)
{
// Create a new family group and get the ID
var familyGroupId = createData.FamilyGroupId ?? CreateFamilyGroup();
// Create the APUser and get the Id
var apUserId = CreateAPUser(createData.UserId, familyGroupId);
// Create the institution user and get the Id
var institutionUserId = CreateInsUser(apUserId, createData.AlternateId, createData.InstitutionId);
// Create the investigator group user and return the Id
return AddUserToGroup(createData.InvestigatorGroupId, institutionUserId);
}
This is an example of one of the function calls, all the other ones follow the same format
public int CreateFamilyGroup(string familyGroupName)
{
var familyRepo = _FamilyRepo ?? new FamilyGroupRepository();
var familyGroup = new FamilyGroup() {CreationDate = DateTime.Now};
return familyRepo.AddFamilyGroup(familyGroup);
}
And the repository call for this is as follows
public int AddFamilyGroup(FamilyGroup familyGroup)
{
using (var context = new GameDbContext())
{
var newGroup = context.FamilyGroups.Add(familyGroup);
context.SaveChanges();
return newGroup.FamilyGroupId;
}
}
I believe this is caused by creating multiple connections within a single TransactionScope
Yes, that is the problem. It does not really matter how you avoid that as long you avoid it. A common thing to do is to have one connection and one EF context per WCF request. You need to find a way to pass that EF context along.
The method AddFamilyGroup illustrates a common anti-pattern with EF: You are using EF as a CRUD facility. It's supposed to me more like a live object graph connected to the database. The entire WCF request should share the same EF context. If you move in that direction the problem goes away.

Asp.net add multiply rows to CRM 2011 (2+ clients/User)

I've extended the customer portal from MS for 2011 with functionality to add an order.
Now i came across a problem when 2 or more user try to create an order at the same time.
first I created the SalesOrder with:
order = new SalesOrder();
order.SalesOrderId = OrderID;
order.Name = string.Format("Order {0}", DateTime.Now);
order.CustomerId = parentCustomer;
order.PriceLevelId = priceLevel.ToEntityReference();
OrderID = XrmContext.Create(order);
and after this i added products(SalesOrderDetail) with a foreach:
foreach (var product in OrdredProducts)
{
productToAdd = new SalesOrderDetail
{
SalesOrderId = new CrmEntityReference(SalesOrder.EntityLogicalName,
OrderID),
ProductId = new EntityReference(Product.EntityLogicalName,
product.ProductID),
Quantity = product.Quantity
};
XrmContext.Create(productToAdd);
}
this works fine when just one user orders something. But if 2+ users I get error for both user.
so I changed the code to this:
order = new SalesOrder();
OrderID = Guid.NewGuid();
order.SalesOrderId = OrderID;
order.Name = string.Format("Order {0}", DateTime.Now); //:d
order.CustomerId = parentCustomer;
order.PriceLevelId = priceLevel.ToEntityReference();
XrmContext.AddObject(order);
foreach (var product in OrdredProducts)
{
productToAdd = new SalesOrderDetail
{
SalesOrderId = new CrmEntityReference(SalesOrder.EntityLogicalName,
OrderID),
ProductId = new EntityReference(Product.EntityLogicalName,
product.ProductID),
Quantity = product.Quantity
};
XrmContext.AddObject(productToAdd);
}
XrmContext.SaveChanges();
Now if 2+ Users orders something, just one User fails not both like the first try.
the Errors I've got as far(every time an other one):
ValidateOpen - Encountered disposed CrmDbConnection when it should not be disposed
SQL timeout expired.
An unexpected error occurred.
Error retrieving next number (currentordernumber) for organization {guid): return value is empty
System.InvalidOperationException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #F60BF6A2
does anyone have some suggestion where the problem could be? is it the SQL Server/CRM Server/IIS/my code or something different?
Additional Information
SQL Server and CRM Server are not on same machine
I get the same error when i test in VS2012 server(back-end is the same SQL/CRM server)
i get the same error when one user runs over IIS and one over VS2012(debugg)
edit
XrmContext is a XrmServiceContext type and this is derived from CrmOrganizationServiceContext and this one is generated with the crmsvcutil
if someone gets the same problem i solved it following:
first i created the SalesOrder and added it to the CRM:
public void AddToCrm(Entity entity)
{
XrmContext.AddObject(entity);
}
then I created all Orders(SalesOrderDetail) and added them to the CRM(same function as above).
And finally i saved it:
public void SaveToCrm()
{
XrmContext.SaveChanges();
}
this behaviour is like a transaction in the database.
so all other Order have to wait till this one is done.

Random failures using CMISQL queries on Alfresco 3.3.0

[Solved, it seems that there was some bug affecting Alfresco 3.3.0, which is no longer present on Alfresco 3.3.0g]
Hi,
I'm using OpenCMIS to retrieve data from Alfresco 3.3, but it's having a very weird behaviour on CMISQL queries. I've googled somebody else with the same problems, but it seems I'm the first one all over the world :), so I guess it's my fault, not OpenCMIS'.
This is how I'm querying Alfresco:
public Class CmisTest {
private static Session sesion;
private static final String QUERY = "select cmis:objectid, cmis:name from cmis:folder where cmis:name='MyFolder'";
public static void main(String[] args) {
// Open a CMIS session with Alfresco
Map<String, String> params = new HashMap<String, String>();
params.put(SessionParameter.USER, "admin");
params.put(SessionParameter.PASSWORD, "admin");
params.put(SessionParameter.ATOMPUB_URL, "http://localhost:8080/alfresco/s/api/cmis");
params.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
params.put(SessionParameter.REPOSITORY_ID, "fa9d2553-1e4d-491b-87fd-3de894dc7ca9");
sesion = SessionFactoryImpl.newInstance().createSession(params);
// Ugly bug in Alfresco which raises an exception if we request more data than it's available
// See https://issues.alfresco.com/jira/browse/ALF-2859
sesion.getDefaultContext().setMaxItemsPerPage(1);
// We repeat the same query 20 times and count the number of elements retrieved each time
for (int i = 0; i < 20; i++) {
List<QueryResult> result = doQuery();
System.out.println(result.size() + " folders retrieved");
}
}
public static List<QueryResult> doQuery() {
List<QueryResult> result = new LinkedList<QueryResult>();
try {
int page = 0;
while (true) {
ItemIterable<QueryResult> iterable = sesion.query(QUERY, false).skipTo(page);
page++;
for (QueryResult qr : iterable) {
result.add(qr);
}
}
} catch (Exception e) {
// We will always get an exception when Alfresco has no more data to retrieve... :(
// See https://issues.alfresco.com/jira/browse/ALF-2859
}
return result;
}
}
As you can see, we just execute the same query, up to 20 times in a row. You would expect the same result each time, wouldn't you? Unfortunately, this is a sample of what we get:
1 folders retrieved
1 folders retrieved
1 folders retrieved
0 folders retrieved
0 folders retrieved
0 folders retrieved
0 folders retrieved
0 folders retrieved
1 folders retrieved
1 folders retrieved
Sometimes we get 20 1 in a row, sometimes it's all 0. We have never get a "mix" of 1 and 0, though; we always get "a run" of them.
It does not matter if we create the session before each query, we still have the random issue. We have tried against two different Alfresco servers (both of them 3.3 Community), clean installation, and they both fail randomly. We also tried to measure the time for each query, but it doesn't seem to have any relation with the result being wrong (0 folders retrieved) or right (1 folders retrieved).
Alfresco seems to be working fine: if we go to "Administration --> Node browser" and launch the CMISQL query from there, it always retrieves one folder, which is right. So, it must be our code, or an OpenCMIS bug...
Any ideas?
I can't reproduce this behavior. It's running fine against http://cmis.alfresco.com . The issue https://issues.alfresco.com/jira/browse/ALF-2859 states that there have been bug fixes. Are you running the latest Alfresco version?
Florian

Resources