OpenIM groups creation issue?

Hello,

I’‘ve written a little java class to go to our database open the users table and generate accounts on openim from those accounts. This all works really well but I’'ve run into a little problem… so let me lay it down for ya…

First I hit the database and build an array of users objects to be create.

I then loop this array and create the account if it doesn’'t exist.

After all the accounts have been created I login as each user and loop the user array again adding those users to that currently logged in user. Each of the user objects in the array have a department property that I’'m setting as the group.

First user gets all the users in the correct groups on the roster list.

Second user it’'s really good but since the first user already added this user to their list the first user shows up in the second users “General” group.

By the time I hit the last user object in the array everyone is added to the “General” group. Thus the problem comes into play…

I wrote another function to correct the group problem but it doesn’'t commit the change for some reason here is the code for the group fix:

public static void checkGroups(CrimsHRData crimsData){
    try {
      //for each user
      CrimsHRData.User theUser;
      CrimsHRData.User theCurrentRosterPerson;
      RosterEntry tmpObj;       if (!crimsData.users.isEmpty()) {
        for (int i = 0; i <= crimsData.users.size() - 1; i++) {
          conn2 = new XMPPConnection(OPENIMSERVER, OPENIMSERVERPORT);           theUser = (CrimsHRData.User) crimsData.users.get(i);
          System.out.println("--- Roster Check For "+theUser.networkLogin+" ---");
          //next login as each of the above users after all accounts have been created
          conn2.login(theUser.networkLogin, OPENIMGLOBALUSERPASSWORD);
          conn2.getRoster().setSubscriptionMode(Roster.SUBSCRIPTION_MANUAL);
          Roster roster = conn2.getRoster();           //check that the people in the list are in the correct groups
          for (Iterator j = roster.getEntries(); j.hasNext(); ) {
            tmpObj = ( (RosterEntry) j.next());
            ArrayList usersGroups = new ArrayList();
            //System.out.println(tmpObj.toString());             for (Iterator jj = tmpObj.getGroups(); jj.hasNext(); ) {
              String tmpStr = ( (RosterGroup) jj.next()).getName();
              usersGroups.add(tmpStr);
              //System.out.println(tmpObj.getUser() + " is a member of " + tmpStr);
            }             //find the current roster user in the master array list and get it''s group
            for (int cp = 0; cp <= crimsData.users.size() - 1; cp++) {
              theCurrentRosterPerson = (CrimsHRData.User) crimsData.users.get(cp);
              if (!theCurrentRosterPerson.networkLogin.equalsIgnoreCase(theUser.networkLogin)) {
                String tmpStr = tmpObj.getUser().substring(0, tmpObj.getUser().indexOf("@"));
                if (theCurrentRosterPerson.networkLogin.equalsIgnoreCase(tmpStr)) {
                  //they are equal lets do the rest of the code then break
                  if (!usersGroups.get(0).toString().equalsIgnoreCase(theCurrentRosterPerson.department)) {                     RosterGroup currGroup = conn2.getRoster().getGroup(usersGroups.get(0).toString());
                    RosterGroup newGroup = conn2.getRoster().getGroup(theCurrentRosterPerson.department.toString());
                    if (newGroup == null){
                      //the group doesn''t exist create it
                      newGroup = conn2.getRoster().createGroup(theCurrentRosterPerson.department.toString());
                      System.out.println(" Added Group: "+theCurrentRosterPerson.department.toString());
                    }
                    RosterEntry entryToMove = currGroup.getEntry(tmpObj.getUser());                     newGroup.addEntry(entryToMove);
                    currGroup.removeEntry(entryToMove);                     //is it not yet commited?  why isn''t it saving the change here                     System.out.println(" -> Moved " + tmpObj.getUser() + " from " + usersGroups.get(0).toString() + " to " + theCurrentRosterPerson.department);
                  }                   break;
                }
                else {
                  //they are not equal try the next one
                }
              } //end if
            }             usersGroups = null;
          }
          conn2.close();
        }
      }
    }
    catch (XMPPException ex) {
      ex.printStackTrace();
    }
  }

It doesn’'t commit the change in groups… why not? what am I missing?

Thanks!

Michael,

First I hit the database and build an array of users objects to be create.

I then loop this array and create the account if it doesn’'t exist.

Ok.

After all the accounts have been created I login as each user and loop the user array again adding those users to that currently logged in user. Each of the user objects in the array have a department property that I’'m setting as the group.

First user gets all the users in the correct groups on the roster list.

Second user it’'s really good but since the first user already added this user to their list the first user shows up in the second users “General” group.

Hmmm, this is strange. Let’‘s say that we have userA and userB. When we add userB to userA’‘s roster in group1 then we end up with group1 in userA that contains a userB. On the other hand we end up with userA as an unfiled entry in userB’‘s roster (if we are using the method SUBSCRIPTION_ACCEPT_ALL in userB’'s roster).

If we then add userA to userB’‘s roster in group2 we should still have the roster of userA unmodified while userB’'s roster should now have a group called group2 containing userA.

This means that, in your case, you shouldn’‘t have users in a group called “General”. All the roster entries (users) should be in their corresponding group (department). If we could take a look at your code we could try to figure out what’'s going on. It would be helpful if you also post the transmitted XML packets (you can use the debugger to get this info).

Regarding the “uncommited changes” it would also be helpful if you post the sent packets (XML). BTW, you shouldn’'t be setting the subscription mode to SUBSCRIPTION_MANUAL unless you register a listener for handling presence packets.

Regards,

– Gato

Right… but that appears to be exactly my problem… sorry code doesn’'t paste in here very nice. Here is the function that I am using to create the users and groups for each user…

public static void createUsersAndGroups(CrimsHRData crimsData){     try {       //ok now that all the accounts have been created login as each of those accounts and edit the roster and groups
      CrimsHRData.User theUser;       if (!crimsData.users.isEmpty()){
        for (int i = 0; i <= crimsData.users.size()-1; i++) {
          conn2 = new XMPPConnection(OPENIMSERVER, OPENIMSERVERPORT);           theUser = (CrimsHRData.User) crimsData.users.get(i);           //next login as each of the above users after all accounts have been created
          conn2.login(theUser.networkLogin,OPENIMGLOBALUSERPASSWORD);
          conn2.getRoster().setSubscriptionMode(Roster.SUBSCRIPTION_MANUAL);
          System.out.println("--- Logged In As: "+theUser.networkLogin+" ---");
          Roster roster = conn2.getRoster();           //list the currently logged in users roster info groups and reg''d users
          ArrayList usersGroups = new ArrayList();           for (Iterator j=roster.getGroups(); j.hasNext(); ) {
            String tmpStr = ((RosterGroup)j.next()).getName();
            usersGroups.add(tmpStr);
            System.out.println(" Existing Group: "+tmpStr);
          }           //create the groups that do not yet exist
          if (!crimsData.groups.isEmpty()){             for (int k=0; k <= crimsData.groups.size()-1; k++) {
              boolean b = false;
              String theGroup = crimsData.groups.get(k).toString();               for (int kk=0; kk <= usersGroups.size()-1; kk++){
                String theUserGroup = usersGroups.get(kk).toString();
                if (!theGroup.equalsIgnoreCase(theUserGroup)) {
                  //!=
                  b = false;
                } else {
                  //in list
                  b = true;
                  break;
                }
              }
              if (b == false) {
                //the group doesn''t exist so lets create it
                System.out.println(" Added Group: "+theGroup);
                conn2.getRoster().createGroup(theGroup);
              }
            }           } else {
            System.out.println("No groups to create.");
          }           //if the user doesn''t exist in the current roster then create the user           ArrayList usersJIDs = new ArrayList();           for (Iterator j = roster.getEntries(); j.hasNext(); ) {
            RosterEntry tmpObj = ((RosterEntry)j.next());
            usersJIDs.add(tmpObj);
            System.out.println(" Exiting Entry: "+tmpObj.toString());
          }           //add users to the roster in the perspective groups
          for (int u = 0; u <= crimsData.users.size()-1; u++) {
            //get the current user item here theRosterAddition
            CrimsHRData.User theRosterAddition = (CrimsHRData.User) crimsData.users.get(u);             boolean b = false;             for (int kk = 0; kk <= usersJIDs.size()-1; kk++) {
              RosterEntry tmpObj = ((RosterEntry)usersJIDs.get(kk));
              theUserJIDs = tmpObj.getUser().substring(0,tmpObj.getUser().indexOf("@"));               //now compare the user and group part of the new user to make sure the user is in the right group
              if (!theRosterAddition.networkLogin.equalsIgnoreCase(theUserJIDs)) {
                //!=
                b = false;
              }
              else {
                //in list
                b = true;
                break;
              }
            }             if (b) {
              //user exists check the group of the user and move to the correct group
              if (!theRosterAddition.networkLogin.equalsIgnoreCase(theUser.networkLogin)) {
                //do nothing at this time we''ll do the group check in the next function
              }             }
            else {
              //the user doesn''t exist so lets create it
              if (!theRosterAddition.networkLogin.equalsIgnoreCase(theUser.networkLogin)) {
                String[] groups = {theRosterAddition.department};
                roster.createEntry(theRosterAddition.networkLogin + "@" + OPENIMSERVER, theRosterAddition.employeeName,groups);
                System.out.println("Added Roster: " + theRosterAddition.networkLogin + "@" + OPENIMSERVER);
              }             }           }           //close connection
          conn2.close();         }       }       System.out.println("--- Accounts Create Done! ---");
    }
    catch (XMPPException ex) {
      ex.printStackTrace();
    }
  }

Here is the function I use that creates the initial accounts

public static void createAccounts(CrimsHRData crimsData){
    try {
    //try to create a new account - loop this code for all valid USIS users creating an account for each
    if (!crimsData.users.isEmpty()){
      System.out.println(crimsData.users.size()+" users to create.");
      for (int i=0; i <= crimsData.users.size()-1; i++){         //check if accounts already exists on the server
        CrimsHRData.User theUser = (CrimsHRData.User)crimsData.users.get(i);
        conn2 = new XMPPConnection(OPENIMSERVER, OPENIMSERVERPORT);
        try {
          //if this works then the account already exists
          conn2.login(theUser.networkLogin, OPENIMGLOBALUSERPASSWORD);
          conn2.getRoster().setSubscriptionMode(Roster.SUBSCRIPTION_MANUAL);
          System.out.println(theUser.networkLogin+" Account Exists!");
          conn2.close();
        }
        catch (XMPPException ex) {
          //if this doesn''t work then the account may not exist so lets create it
          conn2.close();
          conn2 = new XMPPConnection(OPENIMSERVER, OPENIMSERVERPORT);
          conn2.getAccountManager().createAccount(theUser.networkLogin,OPENIMGLOBALUSERPASSWORD);
          //conn2.getRoster().setSubscriptionMode(Roster.SUBSCRIPTION_MANUAL);
          System.out.println(theUser.networkLogin+" Account Created!");
          conn2.close();
        }       }
    } else {
      System.out.println("No users to create.");
    }   }
  catch (XMPPException ex) {
    ex.printStackTrace();
  }
}

Here is the CrimsHRData class that I pass to these functions…

public class CrimsHRData implements Const {
  SqlConnection sqlConn;
  ResultSet rs;
  String className;   public User user;   public class User {
    public int employeeID;
    public int supervisor;
    public String employeeName;
    public String position;
    public String department;
    public String returnEmail;
    public String networkLogin;
  }   public ArrayList users;
  public ArrayList groups;   public CrimsHRData() {
    //tell the logger where we are at and set the opening vars
    className = this.getClass().getName();     //do sql here
    sqlConn = new SqlConnection();     //do other create code here
    GetUsers();
    GetGroups();     //clean up here
    sqlConn.closeConnection();
  }   public void GetUsers(){
    //get the users here
    users = new ArrayList();     //read the info from the tables for the selected valid searchid
    try {
      Statement stmt = sqlConn.getConnection().createStatement();
      rs = stmt.executeQuery(sqlGetUsers);       //loop the record set and add to the users list
      while (rs.next()) {
        user = new User();
        user.employeeID = rs.getInt("employeeidreal");
        user.supervisor = rs.getInt("mysupervisor");
        user.employeeName = rs.getString("employee");
        user.position = rs.getString("position");
        user.department = rs.getString("department");
        user.returnEmail = rs.getString("returnEmail");
        user.networkLogin = rs.getString("networkLogin");
        users.add(user);
      }
      stmt = null;
      rs.close();
    }
    catch (SQLException ex) {
      ex.printStackTrace();
    }
  }   public void GetGroups(){
    //get the current groups here
    groups = new ArrayList();     //read the info from the tables for the selected valid searchid
    try {
      Statement stmt = sqlConn.getConnection().createStatement();
      rs = stmt.executeQuery(sqlGetGroups);       //loop the record set and add to the users list
      while (rs.next()) {
        String group;
        group = rs.getString("department");
        groups.add(group);
      }
      stmt = null;
      rs.close();
    }
    catch (SQLException ex) {
      ex.printStackTrace();
    }
  }   //end of class }

Michael,

I’'ve been reviewing your code and I have a couple of comments and questions.

Comments:

  1. Next time you can post your code between these tags … /c o d e but without the spaces. If you want you can edit your previous posts

  2. There is no need to check for the user’‘s group and create the missing ones since an empty group won’'t be saved in the server. Removing this check makes the code a lot simpler.

So your code would look something like:

//    ok now that all the accounts have been created login as each of those accounts and edit the roster and groups
CrimsHRData.User theUser; if (!crimsData.users.isEmpty()) {
    for (int i = 0; i <= crimsData.users.size() - 1; i++) {
        conn2 = new XMPPConnection(OPENIMSERVER, OPENIMSERVERPORT);         theUser = (CrimsHRData.User) crimsData.users.get(i);         //    next login as each of the above users after all accounts have been created
        conn2.login(theUser.networkLogin, OPENIMGLOBALUSERPASSWORD);
        conn2.getRoster().setSubscriptionMode(Roster.SUBSCRIPTION_MANUAL);
        System.out.println("--- Logged In As: " + theUser.networkLogin + " ---");
        Roster roster = conn2.getRoster();         //    add users to the roster in the perspective groups
        for (int u = 0; u <= crimsData.users.size() - 1; u++) {
            //    get the current user item here theRosterAddition
            CrimsHRData.User theRosterAddition =
                (CrimsHRData.User) crimsData.users.get(u);             //    the user doesn''t exist so lets create it
            if (!theRosterAddition
                .networkLogin
                .equalsIgnoreCase(theUser.networkLogin)) {
                String[] groups = { theRosterAddition.department };
                roster.createEntry(
                    theRosterAddition.networkLogin + "@" + OPENIMSERVER,
                    theRosterAddition.employeeName,
                    groups);
                System.out.println(
                    "Added Roster: "
                        + theRosterAddition.networkLogin
                        + "@"
                        + OPENIMSERVER);
            }
        }
        //    close connection
        conn2.close();
    }
}
System.out.println("--- Accounts Create Done! ---");

Questions:

  1. When you refer to “General” group, are you refering to a group called General or to unfiled entries?

  2. If you are refering to a group called General then the explanation that I have is that theRosterAddition.department has the “General” String value. I’'ll need you to post the transmitted XML to the server (copy this info from the debugger window)

  3. If you are refering to unfiled entries then theRosterAddition.department is null

– Gato

OpenIM released a new version that uses xml config files… thus making it much easier to configure and pre-populate accounts and roster lists! So I just built a tool to work with the xml on the server! I’'m now rockin and rolling! Thanks for the help!

Can you send your openim database class source code to me?! Please!!!

Thanks!!

mail:smoking_boy@msn.com