How to add the value of a custom field in the email notifications in JIRA 5.0

ab185178 September 13, 2012

I have a custom field of the type Select List . I wan to add the value of this field in the email notifications that are sent to the user.

Please let me know how can I do this. I have already had this implemented for JIRA 4.3.4. Is it the same for JIRA 5.0 also.

Amit.

3 answers

1 accepted

0 votes
Answer accepted
Jobin Kuruvilla [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 13, 2012

Almost! If you are using the getCustomFieldValue, it retruns Option object in JIRA5. You need to do a getValue or toString on it.

Did you test it?

ab185178 September 16, 2012

Thanks Jobin for the quick response. I did try this out. I made the changes to the atlassian-jira\WEB-INF\classes\templates\email\text\issuecreated. This is the change:

#if ($issue.getCustomFieldValue("customfield_10703"))
$stringUtils.leftPad($issue.getCustomField("customfield_10703").name, $padSize):$issue.getCustomFieldValue("customfield_10703").getValue()
$stringUtils.leftPad($issue.getCustomField("customfield_10703").name, $padSize):$issue.getCustomFieldValue("customfield_10703").toString()

#end

where customfield_10703 is the custom field created by me of type single select selectlist.

The same changes were made to the issuesummary.vm file located within includes folder at the above location.

Please let me know if this is correct.

Thanks.

Jobin Kuruvilla [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 19, 2012

is it a select list or Version picker?

ab185178 September 19, 2012

Jobin,

Yes I have tested what u advices, but it is not working. I did tried both, getValue and toString. but it did not brought the Version value in the email notification.

Please help me out here.

Thanks.

ab185178 September 19, 2012

Its a single version picker.

Jobin Kuruvilla [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 19, 2012

That is not a select list as you mentioned in the question! I don't think the version manager is available in templates and so you might not get the version name. toString should get you the version id, right?

ab185178 September 19, 2012

Oh!! my bad... Actually .toString does not give anything in the email. Is there any way I can get the Version value in the email notification. I do have this implemented this for JIRA 4.3.4 this way:

$stringUtils.leftPad($issue.getCustomField("customfield_10703").name, $padSize):$issue.getCustomFieldValue("customfield_10703")

ab185178 September 19, 2012

Any Suggestions Jobin??

ab185178 September 19, 2012

Are these the only files that need to modified: issuecreated.vm and issuesummary.vm. I could see that the email that I received follows a different template (I mean that the ordering of the fields is different).

Amit.

ab185178 September 20, 2012

Jobin,

I hope we can achieve this in JIRA 5.0.

Jobin Kuruvilla [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 20, 2012

What event are you trying to get emails for? Do you have html or text format? It is still possible in JIRA but I am not sure what is different for you.

ab185178 September 23, 2012

Please let me know if the code written above is correct or not?

ab185178 September 23, 2012

JIRA 5.0

JIRA 4.3.4

Jobin,

The event that I am using is "issuecreated". The format is text. I have made changes to issuecreated.vm and includes\issuesummary.vm. If you been able to get this working at your end, then probably I might be doing something wroong. I have got this configured in exactly the same manner as in JIRA 4.3.4. In the above screenshot, the first one is JIRA 5.0 (does not include any version info). The second screenshot is JIRA 4.3.4 includes version information.

1 vote
srikanth Asoori maringanti November 26, 2012

I am unable to configure the default value for custom field of type selectlist in jira 4.4.5. I tested this in 4.1.2 it is working fine. Also the default value it is showing me is null. I have attached the code below . The execute method is throwing the following error

2012-11-27 13:56:00,011 QuartzWorker-0 INFO ServiceRunner [plugins.calculate

dfields.scheduler.CalculatedFieldsJob] >> Appfire Custom Field Ext Plugin: Defau

lt value is not configured for custom field:Days In Progress

2012-11-27 13:56:00,011 QuartzWorker-0 ERROR ServiceRunner [org.quartz.core.

JobRunShell] Job DEFAULT.CalculatedFieldsJob threw an unhandled Exception:

java.lang.NullPointerException

at com.appfire.jira.plugins.calculatedfields.scheduler.CalculatedFieldsJ

ob.execute(CalculatedFieldsJob.java:153)

at org.quartz.core.JobRunShell.run(JobRunShell.java:195)

at com.atlassian.multitenant.quartz.MultiTenantThreadPool$MultiTenantRun

nable.run(MultiTenantThreadPool.java:72)

at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.j

ava:520)

2012-11-27 13:56:00,011 QuartzWorker-0 ERROR ServiceRunner [org.quartz.core.

ErrorLogger] Job (DEFAULT.CalculatedFieldsJob threw an exception.

org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exc

eption: java.lang.NullPointerException]

at org.quartz.core.JobRunShell.run(JobRunShell.java:206)

at com.atlassian.multitenant.quartz.MultiTenantThreadPool$MultiTenantRun

nable.run(MultiTenantThreadPool.java:72)

at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.j

ava:520)

* Nested Exception (Underlying Cause) ---------------

java.lang.NullPointerException

at com.appfire.jira.plugins.calculatedfields.scheduler.CalculatedFieldsJ

ob.execute(CalculatedFieldsJob.java:153)

at org.quartz.core.JobRunShell.run(JobRunShell.java:195)

at com.atlassian.multitenant.quartz.MultiTenantThreadPool$MultiTenantRun

nable.run(MultiTenantThreadPool.java:72)

at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.j

ava:520)

//////////////////////////////////////////////////////////////////// Code ////
public class CalculatedFieldsJob implements Job{
private static Logger log = Logger.getLogger(CalculatedFieldsJob.class);
public final static long ONE_SECOND = 1000;
public final static long SECONDS = 60;
public final static long ONE_MINUTE = ONE_SECOND * 60;
public final static long MINUTES = 60;
public final static long ONE_HOUR = ONE_MINUTE * 60;
public final static long HOURS = 24;
public final static long ONE_DAY = ONE_HOUR * 24;
private CustomFieldManager customFieldManager;
private static final String AF_PROPERTIES_FILE = "appfirecalculatedfields.properties";
private static final String AF_USER_KEY_DEFAULT = "calculatedfieldsuser";
private static final String AF_USER_DEFAULT = "admin";
public final String CUSTOMFIELD_KEY = "com.appfire.jira.plugins.customfield.ext.appfire-customfields-ext:af-daysinstatus";
private static Properties clientProperties = null;
public CustomFieldManager getCustomFieldManager() {
return customFieldManager;
}
public void setCustomFieldManager(CustomFieldManager customFieldManager) {
this.customFieldManager = customFieldManager;
}
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
final URL sampleConfigurationFile = ClassLoaderUtils.getResource(AF_PROPERTIES_FILE, CalculatedFieldsJob.class);
clientProperties = new Properties();
if (sampleConfigurationFile == null) {
log.error("<< appfire properties file could not be found ");
}
clientProperties.load(sampleConfigurationFile.openStream());
log.debug("<< Loaded file " + AF_PROPERTIES_FILE);
if (clientProperties == null) {
log.error("<< clientProperties is null ");
}
} catch (Exception e) {
log.error("<< Error loading " + AF_PROPERTIES_FILE + " " + e.getMessage());
e.printStackTrace();
}
String serviceUser = clientProperties.get(AF_USER_KEY_DEFAULT).toString();
try {
if(serviceUser == null || UserUtils.getUser(serviceUser) == null){
log.error(">> Appfire Custom Field Ext Plugin: Configured user in appfirecalculatedfields.properties is not valid user");
log.info("Reverting to 'admin' user");
serviceUser = AF_USER_DEFAULT;
}
} catch (EntityNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
customFieldManager = (CustomFieldManager)ComponentManager.getComponentInstanceOfType(CustomFieldManager.class);
GenericConfigManager genericConfigManager = (GenericConfigManager)ComponentManager.getComponentInstanceOfType(GenericConfigManager.class);
List<CustomField> fieldList = customFieldManager.getCustomFieldObjects();
boolean wasIndexing = ImportUtils.isIndexIssues();
ImportUtils.setIndexIssues(true);
long jobStartTime = context.getFireTime().getTime();
log.info(">> Appfire Custom Field Ext Plugin: Calculated Field job trigerred at: " + context.getFireTime());
for(Iterator itr = fieldList.iterator(); itr.hasNext();){
CustomField cf = (CustomField)itr.next();
CustomFieldType cft = cf.getCustomFieldType();
if(cft.getKey().equals(CUSTOMFIELD_KEY))
{
FieldConfigSchemeManager sm = (FieldConfigSchemeManager) ComponentManager.getComponentInstanceOfType(FieldConfigSchemeManager.class);
long fieldConfigId = ((FieldConfigSchemeImpl) ((List) sm.getConfigSchemesForField(cf)).get(0)).getId();
Object list = genericConfigManager.retrieve(CustomFieldType.DEFAULT_VALUE_TYPE, Long.toString(fieldConfigId));
if(list == null)
{
log.info(">> Appfire Custom Field Ext Plugin: Default value is not configured for custom field:" + cf.getNameKey());
}
//check if the default value is a valid status
ConstantsManager constantsManager = (ConstantsManager) ComponentManager.getComponentInstanceOfType(ConstantsManager.class);
Status status = constantsManager.getStatusByName(list.toString());
if(status == null){
log.info(">> Appfire Custom Field Ext Plugin: Default value configured for custom field:" + cf.getNameKey() + " is not a valid status");
}else{
log.info(">> Appfire Custom Field Ext Plugin: calculating for custom field: " + cf.getName() );
}
long startCFTime = System.currentTimeMillis();
final JqlQueryBuilder builder = JqlQueryBuilder.newBuilder();
// builder.where().status().eq("Open").and().assignee().eq(getRemoteUser().getName());
builder.where().status().eq(status.getName());
//builder.orderBy().createdDate(SortOrder.DESC);
Query query = builder.buildQuery();
SearchService searchService = ComponentManager.getInstance()
.getSearchService();
SearchResults results = null;
try {
User user = UserUtils.getUser(serviceUser);
JiraServiceContextImpl jiraServiceContextImpl = new JiraServiceContextImpl(user);
results = searchService.search(jiraServiceContextImpl.getUser(), query, PagerFilter.getUnlimitedFilter());
List<Issue> issues = results.getIssues();
log.debug(">> Appfire Custom Field Ext Plugin: Number of issues retreived :" + issues.size());
for (int i = 0; i < issues.size(); i++) {
Issue issue = (Issue) issues.get(i);
List<Transition> transList = getTransitionsList(issue);
long cfValue = getDurantionInStatus(issue,transList);
double secs = (double)cfValue/1000;
double days = ((double)secs)/86400d;
NumberFormat formatter = new DecimalFormat("#0.00");
String numDays = formatter.format(days) + " Days";
MutableIssue missue = ComponentManager.getInstance().getIssueManager().getIssueObject(issue.getId());
DefaultIssueChangeHolder issueChangeHolder = new DefaultIssueChangeHolder();
// final ModifiedValue modifiedValue = (ModifiedValue) modifiedFields.get(cf.getId());
cft.updateValue(cf, missue, numDays);
if(i%100 == 0){
log.debug(">> Appfire Custom Field Ext Plugin: updated issues "+ i + ", custom field value for " + cf.getName() + " calculated as:" + numDays + " current time " + new Date());
}
}
}catch (SearchException e) {
log.error(">> Appfire Custom Field Ext Plugin: Error while executing the search query" );
e.printStackTrace();
} catch (EntityNotFoundException e) {
log.error(">> Appfire Custom Field Ext Plugin: Error rereiving the issse " );
e.printStackTrace();
}
//end for a custom field
long timetakenForCF = System.currentTimeMillis() - startCFTime;
String timeforCF = CalculatedFieldsJob.millisToLongDHMS(timetakenForCF);
log.info(">> Appfire Custom Field Ext Plugin: time to complete values for all issues for Custom Field:" + timeforCF );
}
else
continue;
}
long timetakenForCF = System.currentTimeMillis() - jobStartTime;
String timeforJob = CalculatedFieldsJob.millisToLongDHMS(timetakenForCF);
log.info(">> Appfire Custom Field Ext Plugin: calculated fields job finsihed at :" + timeforJob );
}
private long getDurantionInStatus(Issue issue, List<Transition> transList) {
long timeinMS = 0;
Timestamp tChanged = null;
if(transList.size() > 0 )
{
for(Iterator<Transition> iterator = transList.iterator(); iterator.hasNext();){
Transition tran = iterator.next();
if(tran.getFromStatus().getName().equals(issue.getStatusObject().getName())){
timeinMS = timeinMS + tran.getDurationInMillis();
}
if(tran.getToStatus().getName().equals(issue.getStatusObject().getName()))
tChanged = tran.getChangedAt();
}
}
else{
//No transitions, so initial status is being tracked. get the durationfrom the issue created
timeinMS = ( System.currentTimeMillis() - issue.getCreated().getTime());
}
if( tChanged != null)
timeinMS = timeinMS + ( System.currentTimeMillis() - ( tChanged != null ? tChanged.getTime() : 0 ) );
return timeinMS;
}
private List<Transition> getTransitionsList(Issue issue) {
ChangeHistoryManager changeHistoryManager =
(ChangeHistoryManager)ComponentManager.getComponentInstanceOfType(ChangeHistoryManager.class);
List<ChangeHistory> changeHistoryOfIssue = changeHistoryManager.getChangeHistoriesForUser(issue,null);
ConstantsManager constantsManager = (ConstantsManager) ComponentManager.getComponentInstanceOfType(ConstantsManager.class);
Timestamp tsStartDate = issue.getCreated();
List<Transition> transList1 = new ArrayList<Transition>();
for(ChangeHistory changeHistory : changeHistoryOfIssue) {
//long timeCreated = issue.getCreated().getTime();
for(Object o : changeHistory.getChangeItems()) {
GenericValue gv = (GenericValue) o;
if(gv.get("field").equals("status")){
String prevStatus = (String)gv.get("oldstring");
String nextStatus = (String)gv.get("newstring");
Transition tran = new Transition();
tran.setChangedAt(changeHistory.getTimePerformed());
tran.setFromStatus(constantsManager.getStatusByName(prevStatus));
tran.setToStatus(constantsManager.getStatusByName(nextStatus));
tran.setStartAt(tsStartDate);
transList1.add(tran);
//used to calculate the start of next tranistion
tsStartDate = changeHistory.getTimePerformed();
}
}
}
return transList1;
}
public static String millisToLongDHMS(long duration) {
StringBuffer res = new StringBuffer();
long temp = 0;
if (duration >= ONE_SECOND) {
temp = duration / ONE_DAY;
if (temp > 0) {
duration -= temp * ONE_DAY;
res.append(temp).append(" day").append(temp > 1 ? "s" : "")
.append(duration >= ONE_MINUTE ? ", " : "");
}
temp = duration / ONE_HOUR;
if (temp > 0) {
duration -= temp * ONE_HOUR;
res.append(temp).append(" hour").append(temp > 1 ? "s" : "")
.append(duration >= ONE_MINUTE ? ", " : "");
}
temp = duration / ONE_MINUTE;
if (temp > 0) {
duration -= temp * ONE_MINUTE;
res.append(temp).append(" minute").append(temp > 1 ? "s" : "");
}
if (!res.toString().equals("") && duration >= ONE_SECOND) {
res.append(" and ");
}
temp = duration / ONE_SECOND;
if (temp > 0) {
res.append(temp).append(" second").append(temp > 1 ? "s" : "");
}
return res.toString();
} else {
return "0 second";
}
}
}
0 votes
Harish September 23, 2012

Hi Amit,

I have customized the Email body message to include the custom fields in the email body.

I have done in Jira 4.4.5

Please check that the custom field IDs are correct.

I have modified 2 files ;

i. /<jira-installation-folder>/atlassian-jira-4.4.5-standalone/atlassian-jira/WEB-INF/classes/templates/email/text/issuecreated.vm

ii. / <jira-installation-folder>/atlassian-jira-4.4.5-standalone/atlassian-jira/WEB-INF/classes/templates/email/text/includes/issuesummary.vm

Added the below lines of code in the issuecreated.vm and issuesummary.vm files :

#if ($issue.getCustomFieldValue("customfield_10006"))

$stringUtils.leftPad($issue.getCustomField("customfield_10006").name, $padSize): $issue.getCustomFieldValue("customfield_10006")

#end

This is working for me. Hope it helps you. :-)

ab185178 September 23, 2012

Thank you so much guys. I have got this resolved. The email notification is showing me the version value.

Thank you for all your effort.

ab185178 September 23, 2012

Just one more thing. Would you guys know how to do the same thing in the html format. How can I bring the value of the custom field in the html format.

Thanks.

Rahul Savaikar September 3, 2014

Is it also possible to add the Issue Created date to the custom notifications?

Regards,

Rahul

BugInc Admin
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
September 22, 2014

Anyone know which file one has to edit to customise the email when sharing an issue with somebody? I can't figure out what event that corresponds to or where else that might be configured

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events