Resolved: [Not a] Bug with user mail settings and receiveMails?
I used the Java API to modify the receiveMails setting for my own user as a test, and now I no longer receive email updates from any work items. I've verified that the box is checked in the Eclipse client--I also tried unsetting and re-setting it--but still no emails.
Is there possibly a backend issue with this field? I'm going to be making a bunch of updates soon, and to avoid flooding mailboxes I'm modifying many users in the same manner, and don't want to entirely lose email updates to all developers. Some sample code (though I do a little abstracting of the RTC API, so I can't post the whole thing):
private static final String MAIL_SETTINGS = "com.ibm.team.workitem.mail.Configuration";
|
Accepted answer
The server on which the repository was running did, in fact, have an email outage. This API is working fine, but what a coincidence...
Ralph Schoon selected this answer as the correct answer
|
One other answer
I wrote this to turn off/restore users emails during mass updates
takes a file of userids (1 per line) or an xml file (you might have one, but have to update the format). the code figures out what kind of source file it is. | updated to use product provided constants instead of hard coded literals. | added support for decypting password | see the second answer here https://jazz.net/forum/questions/156705/is-there-support-for-password-files-in-the-plain-java-client-api | for info on encrypting the password <code> package com.sd.test; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collections; import javax.xml.parsers.DocumentBuilderFactory; import org.eclipse.core.runtime.CoreException; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import com.ibm.team.foundation.common.util.IMemento; import com.ibm.team.foundation.common.util.XMLMemento; import com.ibm.team.repository.client.IContributorManager; import com.ibm.team.repository.client.IItemManager; import com.ibm.team.repository.client.ITeamRepository; import com.ibm.team.repository.client.TeamPlatform; import com.ibm.team.repository.client.ITeamRepository.ILoginHandler; import com.ibm.team.repository.client.ITeamRepository.ILoginHandler.ILoginInfo; import com.ibm.team.repository.common.IContributor; import com.ibm.team.repository.common.IContributorDetails; import com.ibm.team.repository.common.IContributorDetailsHandle; import com.ibm.team.repository.common.IExtensibleItem; import com.ibm.team.repository.common.ItemNotFoundException; import com.ibm.team.repository.common.TeamRepositoryException; import com.ibm.team.workitem.common.internal.mailconfig.IMailConfigurationConstants; import com.ibm.team.repository.common.util.ObfuscationHelper; public class BulkConfigureContributorEmail implements IMailConfigurationConstants { // our hash key to save the content private static final String CONFIG_KEY_ORIGINAL = CONFIG_KEY+".original"; // the default string, cut/pasted private static final String DefaultSettings="default"; private static final String DefaultSettingsString= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<mailconfiguration version=\"0.6\">\r\n<"+CONFIG_SCOPE_GLOBAL+">\r\n<"+CONFIG_DOMAIN_WORK_ITEMS+">\r\n<"+CONFIG_RECEIVE_MAILS+" value=\"true\"/>\r\n<"+CONFIG_MAIL_WHEN_SUBSCRIBED+" value=\"true\"/>\r\n<filter>\r\n<CREATOR>\r\n<COMMENT_ADDED/>\r\n<SUMMARY_DESCRIPTION_CHANGED/>\r\n<SEVERITY_PRIORITY_TARGET_CHANGED/>\r\n<OWNER_CHANGED/>\r\n<TAG_CHANGED/>\r\n<LINKS_ADDED_REMOVED/>\r\n<WORK_ITEM_CREATED_REOPENED/>\r\n<WORK_ITEM_COMPLETED/>\r\n<OTHER_STATE_CHANGE/>\r\n<OTHER_CHANGE/>\r\n</CREATOR>\r\n<OWNER>\r\n<COMMENT_ADDED/>\r\n<SUMMARY_DESCRIPTION_CHANGED/>\r\n<SEVERITY_PRIORITY_TARGET_CHANGED/>\r\n<OWNER_CHANGED/>\r\n<TAG_CHANGED/>\r\n<LINKS_ADDED_REMOVED/>\r\n<WORK_ITEM_CREATED_REOPENED/>\r\n<WORK_ITEM_COMPLETED/>\r\n<OTHER_STATE_CHANGE/>\r\n<OTHER_CHANGE/>\r\n</OWNER>\r\n<SUBSCRIBER>\r\n<COMMENT_ADDED/>\r\n<SUMMARY_DESCRIPTION_CHANGED/>\r\n<SEVERITY_PRIORITY_TARGET_CHANGED/>\r\n<OWNER_CHANGED/>\r\n<TAG_CHANGED/>\r\n<LINKS_ADDED_REMOVED/>\r\n<WORK_ITEM_CREATED_REOPENED/>\r\n<WORK_ITEM_COMPLETED/>\r\n<OTHER_STATE_CHANGE/>\r\n<OTHER_CHANGE/>\r\n</SUBSCRIBER>\r\n</filter>\r\n</"+CONFIG_DOMAIN_WORK_ITEMS+">\r\n<"+CONFIG_DOMAIN_MESSAGES_AT_ME+">\r\n<"+CONFIG_MAIL_MESSAGES_AT_ME+" value=\"true\"/>\r\n</"+CONFIG_DOMAIN_MESSAGES_AT_ME+">\r\n<approvals>\r\n<"+CONFIG_RECEIVE_MAILS+" value=\"true\"/>\r\n<receiveOwnChanges value=\"false\"/>\r\n</approvals>\r\n<format>\r\n<htmlMail value=\"false\"/>\r\n</format>\r\n</"+CONFIG_SCOPE_GLOBAL+">\r\n</mailconfiguration>"; // the identifier for the xml content to get to a user entry private static final String XMLElementName = "Row"; private static final String UserIDElementName ="ID"; private static final String operationDisable = "disable"; private static final String operationRestore = "restore"; private static class LoginHandler implements ILoginHandler, ILoginInfo { private String fUserId; private String fPassword; private LoginHandler(String userId, String password) { fUserId = userId; fPassword = password; } public String getUserId() { return fUserId; } public String getPassword() { return fPassword; } public ILoginInfo challenge(ITeamRepository repository) { return this; } } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub String repositoryURI = args[0]; String AdminUserId = args[1]; String password = args[2]; String UserlistFile = args[3]; String operation = args[4]; TeamPlatform.startup(); ITeamRepository teamRepository = TeamPlatform .getTeamRepositoryService().getTeamRepository(repositoryURI); try { // decrypt the user password password = ObfuscationHelper.decryptString(password); } catch(Exception ex) { // nothin to do, variable not overlayed on error } teamRepository.registerLoginHandler(new LoginHandler(AdminUserId, password)); // get the list of users whose email config needs to be changed // might be flat file of ids, or xml doc Rows><Row <id>name</id> // get the list ready here, if that fails. don't continue ArrayList<String> userids = getUseridList(UserlistFile); if(userids.size()>0) { try { // login teamRepository.login(null); // if successful if(teamRepository.loggedIn()) { // get the two workers IContributorManager icm; icm = teamRepository.contributorManager(); IItemManager iim; iim = teamRepository.itemManager(); // loop thru the userid array for(String userid: userids) { try { // get the user record using the ID string (not the name) IContributor contributor = icm.fetchContributorByUserId(userid, null); // if we found the user in the system if(contributor!=null) { // get the read/write copy of the contributor record contributor = (IContributor) contributor.getWorkingCopy(); // set the mail config // either disabled, all // or restored to whatever it was setMailConfiguration(contributor,icm, iim, operation); } } catch(ItemNotFoundException ex) { continue; } } } } catch(Exception ex) { System.out.println("exception="+ex.toString()); } } TeamPlatform.shutdown(); } public static ArrayList<String> getUseridList(String filename) { ArrayList<String> userlist = new ArrayList<String>(); try { String line; BufferedReader br = new BufferedReader(new FileReader(filename)); // read the first line line= br.readLine(); // if not an xml file if(!line.startsWith("<?xml")) { // save the line to the array userlist.add(line); // read the rest of the user id list while((line = br.readLine()) != null) userlist.add(line); // close the file br.close(); } else { // close the file br.close(); // xml file processor // document handler will reopen and parse Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(filename));; // normalize text representation doc.getDocumentElement().normalize(); // get the list of elements that represent users NodeList listOfUsers = doc.getElementsByTagName(XMLElementName); //System.out.println("Total no of people : " + listOfUsers.getLength()); // loop thru the nodes for(int i=0;i<listOfUsers.getLength(); i++) { NodeList userentry = (NodeList) listOfUsers.item(i); //System.out.println("there are "+ userentry.getLength() + " nodes for this entry"); for (int q=0; q<userentry.getLength();q++) { //System.out.println("node "+ q+ " name="+userentry.item(q).getNodeName()+ " value="+userentry.item(q).getFirstChild().getTextContent()); // find the specific element that contains the userid data if(userentry.item(q).getNodeName().equalsIgnoreCase(UserIDElementName)) { // get the actual user data.. in the Text node // and save it to the array userlist.add(userentry.item(q).getFirstChild().getTextContent()); break; } } } } } catch (Exception ex) { // TODO Auto-generated catch block ex.printStackTrace(); } return userlist; } private static IMemento setMailConfiguration(IContributor contributor,IContributorManager icm, IItemManager iim, String operation) throws TeamRepositoryException { IContributorDetailsHandle detailsHandle= contributor.getDetails(); if (detailsHandle != null) { IContributorDetails details= (IContributorDetails) iim.fetchPartialItem(detailsHandle, IItemManager.REFRESH, Collections.singleton(IExtensibleItem.ALL_STATE_EXTENSIONS_PROPERTY),null); // get the writeable copy of the details details=(IContributorDetails) details.getWorkingCopy(); // if we are restoring the previously set values if(operation.equalsIgnoreCase(operationRestore)) { // get the saved value, if any String configVal= details.getLargeStringExtension(CONFIG_KEY_ORIGINAL); if(configVal!=null) { // if the email value was actually specified if(!configVal.equals(DefaultSettings)) // restore it // overlay the current settings with the original saved value details.setLargeStringExtension(CONFIG_KEY, configVal); else // clear the string, system uses the default details.unsetLargeStringExtension(CONFIG_KEY); // and remove the saved value details.unsetLargeStringExtension(CONFIG_KEY_ORIGINAL); // save the details info back; icm.setContributorDetails(contributor, details,null); } return null; } else if(operation.equalsIgnoreCase(operationDisable)) { // get the saved value, if any String configVal= details.getLargeStringExtension(CONFIG_KEY_ORIGINAL); // do we have a previously saved setup // no continue on if(configVal==null) { // get the RTC data for the mail settings configVal= details.getLargeStringExtension(CONFIG_KEY); // if not set if(configVal==null) { // indicate the defaults were used details.setLargeStringExtension(CONFIG_KEY_ORIGINAL, DefaultSettings); // get the original string copy configVal = DefaultSettingsString; } else { // save the original settings details.setLargeStringExtension(CONFIG_KEY_ORIGINAL, configVal); } try { XMLMemento imx = XMLMemento.createReadRoot(new StringReader(configVal)); // turn off the global emails imx.getChild(CONFIG_SCOPE_GLOBAL).getChild(CONFIG_DOMAIN_WORK_ITEMS).getChild(CONFIG_RECEIVE_MAILS).putString("value", "false"); // and the subscriptions imx.getChild(CONFIG_SCOPE_GLOBAL).getChild(CONFIG_DOMAIN_WORK_ITEMS).getChild(CONFIG_MAIL_WHEN_SUBSCRIBED).putString("value", "false"); // and the mentions imx.getChild(CONFIG_SCOPE_GLOBAL).getChild(CONFIG_DOMAIN_MESSAGES_AT_ME).getChild(CONFIG_MAIL_MESSAGES_AT_ME).putString("value", "false"); // and the approvals imx.getChild(CONFIG_SCOPE_GLOBAL).getChild(CONFIG_DOMAIN_APPROVALS).getChild(CONFIG_RECEIVE_MAILS).putString("value", "false"); StringWriter writer= new StringWriter(); // flush into writer imx.save(writer); // save the new settings details.setLargeStringExtension(CONFIG_KEY, writer.toString()); // and write back to the contributor icm.setContributorDetails(contributor, details,null); } catch (CoreException e) { System.out.println("unable to get contrinutor details"); return (IMemento)null; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return (IMemento)null; } return (IMemento)null; } } </code> Comments
Sterling Bates
commented Dec 23 '13, 1:47 p.m.
Thanks Sam, though the code I have does work. It turns out that it might be a repo-wide issue at the server (vacations are heavy at this time so we didn't find out very quickly) and I'll report back when we know for sure.
Hi Sam,
sam detweiler
commented Nov 03 '15, 6:12 p.m.
sorry, not sure what you mean..
Christiano Monteiro
commented Nov 04 '15, 8:06 a.m.
Sam,
Christiano Monteiro
commented Nov 04 '15, 8:52 a.m.
Sam,
I was posting at the same time.. yes.. you found it..
Please see Skip Mail Save Parameter since RTC 6.0 iFix03.
sam detweiler
commented Oct 11 '16, 10:23 a.m.
while interesting, this doesn't really help in the use cases I see.. bulk import of workitems.. none of my code is involved.
Ralph Schoon
commented Oct 11 '16, 10:34 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER
I hooked your code answer directly to my blog in one case. Want to make sure they see it if they go here.
showing 5 of 9
show 4 more comments
|
Your answer
Dashboards and work items are no longer publicly available, so some links may be invalid. We now provide similar information through other means. Learn more here.
Comments
Sterling,
I have written a code to update mail format settings - it fails to fetch the contributor details and throuws null exception on the mailconfig retrieval:
*It works after i open the particular user in the editor and perform a save.
user = icm.fetchContributorByUserId(userid, null);
contributorWorkingCopy = (IContributor) user.getWorkingCopy();
icm.saveContributor(contributorWorkingCopy, null);
IContributorDetailsHandle detailsHandle = contributorWorkingCopy.getDetails();
details = (IContributorDetails) iim.fetchCompleteItem(detailsHandle,IItemManager.DEFAULT, null);
details=(IContributorDetails) details.getWorkingCopy();
String mailconfig = details.getLargeStringExtension("com.ibm.team.workitem.mail.Configuration");
mailconfig value is retrieved as null.Please advise.
Thanks. So, in RTC how can we this feature usage ? Is it a contribution to development? Please help.