| This documentation is in-progress. But this is enough to get started. |
Creating a new Issue
| There are different ways of getting the MutableIssue object depending on which version of JIRA you are using.
If you are using JIRA 3.6.5 and below then you will call: MutableIssue issueObject = (MutableIssue) JiraUtils.loadComponent(IssueImpl.class); If you are using JIRA 3.7 and above then you will call: MutableIssue issueObject = issueFactory.getIssue(); As mentioned below you can get a handle on an IssueFactory either by Constructor Injection or explicitly via a call like: ComponentManager.getInstance().getIssueFactory() |
Here is sniplet of code that creates a new issue:
// Use this if you are using JIRA 3.6.5 and below
//MutableIssue issueObject = (MutableIssue) JiraUtils.loadComponent(IssueImpl.class);
// Use this if you are using JIRA 3.7 and above
MutableIssue issueObject = issueFactory.getIssue();
// Regular Fields
issueObject.setProject(projectManager.getProject(new Long(10000)));
issueObject.setIssueType(constantsManager.getIssueType("1"));
issueObject.setSummary("Test Issue");
issueObject.setReporter(UserUtils.getUser("admin"));
issueObject.setAssignee(UserUtils.getUser("admin"));
issueObject.setPriority(constantsManager.getPriority("1"));
issueObject.setDescription("Test description");
issueObject.setAffectedVersions(EasyList.build(versionManager.getVersion(new Long(10000)), versionManager.getVersion(new Long(10001))));
issueObject.setFixVersions(EasyList.build(versionManager.getVersion(new Long(10002))));
issueObject.setComponents(EasyList.build(projectManager.getComponent(new Long(10000)), projectManager.getComponent(new Long(10001))));
// Custom Fields
CustomField customField = customFieldManager.getCustomFieldObject(new Long(10020));
issueObject.setCustomFieldValue(customField, "Test Value");
Map params = new HashMap();
params.put("issue", issueObject);
GenericValue issue = issueManager.createIssue(authenticationContext.getUser(), params);
This code example uses a lot of Manager objects. You can get a reference to them by declaring a dependency in the constructor of your plugin.
Classes not managed by Picocontainer (eg. workflow conditions / functions, Services and Listeners, or JSP scriptlets) can still get pico-instantiated objects statically using static methods of ManagerFactory or ComponentManager.getInstance(). For example:
ComponentManager.getInstance().getProjectManager(); ComponentManager.getInstance().getIssueFactory(); ManagerFactory.getCustomFieldManager(); //or ManagerFactory.getApplicationProperties();
Using ComponentManager.getInstance() is prefered as ManagerFactory will become obsolete. However, if a method that you are after does not exist on the ComponentManager, use ManagerFactory.
The code above also sets a value for a custom field on the issue. Please note that the value must be an object of the type that the Custom Field expects. As the above code was using a Text custom field, a simple java.lang.String is fine. For more information on working with custom fields please see Working with Custom Fields.
Editing an existing Issue
The code below edits a Due Date field of an issue and sets it to 24 hours from now. A comment that is visible by everyone who has permission to see the issue is also added.
MutableIssue issue = issueFactory.getIssue(issueGV);
issue.setDueDate(new Timestamp(System.currentTimeMillis() + 24*60*60*1000));
Map actionParams = EasyMap.build("issue", issue.getGenericValue(), "issueObject", issue, "remoteUser", authenticationContext.getUser());
actionParams.put("comment", "Test Comment");
actionParams.put("commentLevel", null);
ActionResult aResult = CoreFactory.getActionDispatcher().execute(ActionNames.ISSUE_UPDATE, actionParams);
You can also specify a group name as the commentLevel parameter to restrict the visibility of comments. If you use the above code to update an issue all the relevant change history entries will be made, and an Updated Issue Event generated.
The code above created an issue object from an issue GenericValue.
You can retrieve the issue generic value using the following code:
// By Id
GenericValue issueGV1 = issueManager.getIssue(new Long(10000));
// By Issue Key
GenericValue issueGV2 = issueManager.getIssue("TST-1");
To learn how to update custom fields please see Working with Custom Fields.
Events
It's worth noting that in the examples above, when the issues are created or modified events are fired, and any notifications that are associated with those events will be triggered.






Comments (9)
Dec 15, 2006
Matt Doar says:
If I want to get a local copy of a MutableIssue and modify it, but then not actu...If I want to get a local copy of a MutableIssue and modify it, but then not actually write the changes to the database (i.e. no execute call), am I ok? Or do some of the issue.setFoo() methods in fact modify data that other users will see before it is written back to the database?
May 28, 2007
Dylan Etkin says:
Hi Matt, Sorry for the long delay, the answer is that you are safe to modify th...Hi Matt,
Sorry for the long delay, the answer is that you are safe to modify the in-memory object as long as you don't call the store method.
Feb 15, 2007
Pablo Costa says:
Please, could someone explain how to get a reference to authenticationContext? I...Please, could someone explain how to get a reference to authenticationContext? I am working on a workflow post function plugin. Thanks!
May 28, 2007
Dylan Etkin says:
Hi Pablo, Sorry for the long delay. You can get the AuthenticationContext by ca...Hi Pablo,
Sorry for the long delay. You can get the AuthenticationContext by calling:
Jun 11, 2007
Slawomir Zielina says:
Created issue is not visible in project/issues browser. However it may be oppene...Created issue is not visible in project/issues browser. However it may be oppened giving valid url.. It has correct status,(Open), is in correct project and so on. What else should be set to get this working?
Nov 21, 2007
Simone Ferrari says:
I have a problem after issue creation ... I can find this new issue from "FIND I...I have a problem after issue creation ... I can find this new issue from "FIND ISSUE" or an other filter like "Added Recently". I can find the issue only if I "reindex".
This is the code to create an issue
MutableIssue newIssue = issueFactory.getIssue();
newIssue.setProject(projectManager.getProject(issue.getGenericValue()));
newIssue.setSummary(summary);
newIssue.setIssueTypeId(issueTypeId);
// Il reporter di questa transizione sarà il reporter della issue di partenza
newIssue.setReporter(issue.getReporter());
newIssue.setFixVersions(EasyList.build(versionToFix));
newIssue.setPriorityId(issue.getPriorityObject().getId());
Map fields = new HashMap();
fields.put("issue", newIssue);
CustomFieldManager customFieldManager = ComponentManager.getInstance().getCustomFieldManager();
{
// Give the CustomFields a chance to set their default values JRA-11762
List customFieldObjects = customFieldManager.getCustomFieldObjects(newIssue);
for (Iterator iteratorCF = customFieldObjects.iterator(); iteratorCF.hasNext()
CustomField customFieldIterated = (CustomField) iteratorCF.next();
if ((customer != null) && (customFieldIterated.getName().equals("Customer")))
else
}
fields.put(WorkflowFunctionUtils.ORIGNAL_ISSUE_KEY, issue);
try
catch (CreateException e)
Jan 30, 2008
M. David Minnigerode says:
Updating an Issue In 3.12: Figured out that there are two aspects to this. The...Updating an Issue
In 3.12: Figured out that there are two aspects to this. The normal fields... and the workflow.
You can update a field with:
MutableIssue u = getIssueManager().getIssueObject(sourceIssueKey); u.setDescription("New Stuff" + u.getDescription()); ... etc ... u.store();This will persist the change. Suspect it won't fire an update event. Dunno for sure tho.
However. If you want to change the resolution/status you'll need to do a workflow action. You can do the above
but the workflow state of the issue won't get updated correctly and things will get weird.
MutableIssue u = getIssueManager().getIssueObject(sourceIssueKey); u.setResolutionId("9"); // 9 is migrated *our custom resolution* u.setStatusId("6"); // 6 is closed // get's the workflow active for the given issue. JiraWorkflow w = ComponentManager.getInstance().getWorkflowManager().getWorkflow(u); WorkflowManager wm = ComponentManager.getInstance().getWorkflowManager(); // Impls WorkflowAware interface for you. WorkflowTransitionUtil wu = (WorkflowTransitionUtil)JiraUtils.loadComponent(WorkflowTransitionUtilImpl.class); wu.setIssue(u); wu.setUsername(getRemoteUser().getName()); wu.setAction(2); // close workflow action id ErrorCollection col = wu.validate(); log.debug("error collection: " + col); if(col.hasAnyErrors()){ log.error("Cant do it due to workflow errors."); }else{ // Does the workflow tx and stores the updated issue. try{ col = wu.progress(); }catch(Exception e){ log.debug("errors are: " + col , e); } }Resolution id and status id are of course global. The action id's also appear to be global. For something like CLOSE
you're pretty safe. For custom actions... ymmv.
Apr 16, 2009
Matt Doar says:
I seem to have had some success with custom statuses, workflow steps and step id...I seem to have had some success with custom statuses, workflow steps and step ids with the following code.
First we cache all the status objects we are going to want later on.
// workflow Mappings are cached here wfStatusMap = new HashMap(); // Get all the status names and ids. Custom statuses start at 10000 Collection statuses = constantsManager.getStatusObjects(); Iterator statusIter = statuses.iterator(); while (statusIter.hasNext()) { Status status = (Status) statusIter.next(); wfStatusMap.put(status.getId(), status); }now for the method to set the values in the issue itself.
/** * Given an issue, update the underlying workflow, so that it * matches the issue's status. For more information, see * http://confluence.atlassian.com/display/JIRA/Issue+status+and+workflow * * @param issue issue generic value * @throws GenericEntityException if workflow step fails to be persisted */ private void setCurrentWorkflowStep(GenericValue issue) throws GenericEntityException, WorkflowException { // Retrieve the wfCurrentStep for this issue and change it Collection wfCurrentStepCollection = genericDelegator.findByAnd("OSCurrentStep", EasyMap.build("entryId", issue.getLong("workflowId"))); GenericValue wfCurrentStep = (GenericValue) getOnly(wfCurrentStepCollection); Status status = (Status) wfStatusMap.get(issue.getString("status")); // This is the step id in the workflow and affects the actions // available to this issue for changing the status. This value // depends on the project, issue type and the associated // workflow scheme and workflow. That is, Linked Status gives // the associated Workflow Step Name and stepId final JiraWorkflow workflow = workflowManager.getWorkflow(issue); final StepDescriptor linkedStep = workflow.getLinkedStep(status.getGenericValue()); if (linkedStep != null) { wfCurrentStep.set("stepId", new Integer(linkedStep.getId())); } else { // If this is unexpected, check that the JIRA project is using // the workflow scheme and workflow you think it is. log.error("Issue " + issue.getString("key") + " uses the workflow " + workflow.getName() + " which does not have a step for the status " + status.getName()); } // This is the same as the status name in the jiraissue wfCurrentStep.set("status", status.getName()); wfCurrentStep.store(); }May 12, 2008
Dev says:
Hi, I tried to executed the same code as above in JSP but it threw Null pointer...Hi,
I tried to executed the same code as above in JSP but it threw Null pointer Exception . Can some one please help me to get rid of this error?.
Below is the code and error :--
IssueFactory issueFactory = ComponentManager.getInstance().getIssueFactory();
ProjectManager projectManager = ComponentManager.getInstance().getProjectManager();
ConstantsManager constantsManager = ComponentManager.getInstance().getConstantsManager();
VersionManager versionManager = ComponentManager.getInstance().getVersionManager();
CustomFieldManager customFieldManager = ComponentManager.getInstance().getCustomFieldManager();
IssueManager issueManager = ComponentManager.getInstance().getIssueManager();
JiraAuthenticationContext authenticationContext = ComponentManager.getInstance().getJiraAuthenticationContext();
//ManagerFactory.getCustomFieldManager();
//ManagerFactory.getApplicationProperties();
// Use this if you are using JIRA 3.7 and above
MutableIssue issueObject = issueFactory.getIssue();
// Regular Fields
issueObject.setProject(projectManager.getProject(new Long(10000)));
issueObject.setIssueType(constantsManager.getIssueType("1"));
issueObject.setSummary("Test Issue by Devidas");
issueObject.setReporter(UserUtils.getUser("devidask"));
issueObject.setAssignee(UserUtils.getUser("devidask"));
issueObject.setPriority(constantsManager.getPriority("1"));
issueObject.setDescription("Test description by Devidas");
issueObject.setAffectedVersions(EasyList.build(versionManager.getVersion(new Long(10000)), versionManager.getVersion(new Long(10001))));
issueObject.setFixVersions(EasyList.build(versionManager.getVersion(new Long(10002))));
issueObject.setComponents(EasyList.build(projectManager.getComponent(new Long(10000)), projectManager.getComponent(new Long(10001))));
// Custom Fields
//CustomField customField = customFieldManager.getCustomFieldObject(new Long(10020));
//issueObject.setCustomFieldValue(customField, "Test Value");
Map params = new HashMap();
params.put("issue", issueObject);
GenericValue issue = issueManager.createIssue(authenticationContext.getUser(), params);
System.out.println("Issue Created....");
ERROR :--
==============
java.lang.NullPointerException
at com.atlassian.jira.issue.fields.AbstractVersionsSystemField.updateIssueValue(AbstractVersionsSystemField.java:401)
at com.atlassian.jira.issue.fields.AbstractVersionsSystemField.createValue(AbstractVersionsSystemField.java:417)
at com.atlassian.jira.workflow.function.issue.IssueCreateFunction.execute(IssueCreateFunction.java:84)
at com.opensymphony.workflow.AbstractWorkflow.executeFunction(AbstractWorkflow.java:869)
at com.opensymphony.workflow.AbstractWorkflow.transitionWorkflow(AbstractWorkflow.java:1265)
at com.opensymphony.workflow.AbstractWorkflow.initialize(AbstractWorkflow.java:618)
at com.atlassian.jira.workflow.SimpleWorkflowManager.createIssue(SimpleWorkflowManager.java:189)
at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:365)
at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:313)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at com.atlassian.util.profiling.object.ObjectProfiler.profiledInvoke(ObjectProfiler.java:71)
at com.atlassian.jira.config.component.SwitchingInvocationHandler.invoke(SwitchingInvocationHandler.java:28)
at $Proxy3.createIssue(Unknown Source)
at org.apache.jsp.TestPage_jsp._jspService(TestPage_jsp.java:136)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:334)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at com.atlassian.jira.web.filters.AccessLogFilter.doFilter(AccessLogFilter.java:73)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:119)
at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:55)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at com.atlassian.seraph.filter.SecurityFilter.doFilter(SecurityFilter.java:182)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at com.atlassian.seraph.filter.LoginFilter.doFilter(LoginFilter.java:181)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at com.atlassian.util.profiling.filters.ProfilingFilter.doFilter(ProfilingFilter.java:132)
at com.atlassian.jira.web.filters.JIRAProfilingFilter.doFilter(JIRAProfilingFilter.java:16)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)