- 
    Bug 
- 
    Resolution: Fixed
- 
    Low 
- 
    4.0, 6.1.5
- 
        4
- 
        
Problem:
Since JIRA 4.0 (after implementing JRA-15723), JIRA does not set the Updated Date correctly on issues when being called using:
public Comment create(Issue issue, ApplicationUser author, ApplicationUser updateAuthor, String body, String groupLevel, Long roleLevelId, Date created, Date updated, boolean dispatchEvent, boolean tweakIssueUpdateDate)
CommentManager.java - Java docs
  /**
     * Creates a comment and associates it with the given issue. Using this method the comment will be created
     * with a createdDate of the specified date. This method should be used if you are trying to preserve existing
     * information and it is important to retain the original created date. If you have provided a groupLevel then the
     * comment visibility will be restricted to the provided group, it is assumed that validation to ensure that the
     * group actually exists has been performed outside of this method. If you have provided a roleLevelId then the
     * comment visibility will be restricted to the provided role, it is assumed that validation to ensure that the
     * role actually exists has been performed outside of this method.
     * <p/>
     * <strong>NOTE:</strong> A comment should not have both a group level and role level visibility restriction. This
     * method will not stop this, but it does not semantically make sense.
     *
     * @param issue                the issue to associate the comment with.
     * @param author               the key of the user who has created this comment.
     * @param updateAuthor         the key of the user who has updated this comment last
     * @param body                 the text of the comment.
     * @param groupLevel           is the group name to limit comment visibility to, this must be a valid group name.
     * @param roleLevelId          is the id of the the {@link ProjectRole} to limit comment visibility to, this must reference a
     *                             valid project role.
     * @param created              is the date that will be used as the comments creation date.
     * @param updated              is the date that will be used as the comments updated date.
     * @param dispatchEvent        if true then an event of type {@link com.atlassian.jira.event.type.EventType#ISSUE_COMMENTED_ID}
     *                             will be dispatched and any notifications listening for that event will be triggered.
     *                             If false no event will be dispatched.
     * @param tweakIssueUpdateDate if true the issues 'updated' date will be set to now.
     * @return the object representation of the newly created comment.
     */
    public Comment create(Issue issue, ApplicationUser author, ApplicationUser updateAuthor, String body, String groupLevel, Long roleLevelId, Date created, Date updated, boolean dispatchEvent, boolean tweakIssueUpdateDate);
tweakIssueUpdateDate if true the issues 'updated' date will be set to now.
Judging by the above, setting the last boolean to true would make JIRA use the current date/time as the update date for the issue. However, in the DefaultCommentManager.java:
    /**
     * @see com.atlassian.jira.issue.comments.CommentManager#create(com.atlassian.jira.issue.Issue,ApplicationUser,ApplicationUser,String,String,Long,java.util.Date,java.util.Date,boolean,boolean)
     */
    @Override
    public Comment create(Issue issue, ApplicationUser author, ApplicationUser updateAuthor, String body, String groupLevel, Long roleLevelId, Date created, Date updated, boolean dispatchEvent, boolean tweakIssueUpdateDate)
            throws DataAccessException
    {
        if (textFieldCharacterLengthValidator.isTextTooLong(body))
        {
            final long maximumNumberOfCharacters = textFieldCharacterLengthValidator.getMaximumNumberOfCharacters();
            String errorMessage = getText("field.error.text.toolong", String.valueOf(maximumNumberOfCharacters));
            throw new IllegalArgumentException(errorMessage);
        }
        // create new instance of comment
        CommentImpl comment = new CommentImpl(this, author, updateAuthor, body, groupLevel, roleLevelId, created, updated, issue);
        // create persistable generic value
        Map<String, Object> fields = new HashMap<String, Object>();
        fields.put("issue", issue.getId());
        fields.put("type", ActionConstants.TYPE_COMMENT);
        ApplicationUser commentAuthor = comment.getAuthorApplicationUser();
        ApplicationUser commentUpdateAuthor = comment.getUpdateAuthorApplicationUser();
        fields.put("author", commentAuthor == null ? null : commentAuthor.getKey());
        fields.put("updateauthor", commentUpdateAuthor == null ? null : commentUpdateAuthor.getKey());
        fields.put("body", comment.getBody());
        fields.put("level", comment.getGroupLevel());
        fields.put("rolelevel", comment.getRoleLevelId());
        fields.put("created", new Timestamp(comment.getCreated().getTime()));
        fields.put("updated", new Timestamp(comment.getUpdated().getTime()));
        GenericValue commentGV = EntityUtils.createValue(COMMENT_ENTITY, fields);
        // set the ID on comment object
        comment.setId(commentGV.getLong(COMMENT_ID));
        // Update the issue object if require
        if (tweakIssueUpdateDate)
        {
            IssueFactory issueFactory = ComponentAccessor.getComponentOfType(IssueFactory.class);
            MutableIssue mutableIssue = issueFactory.getIssue(issue.getGenericValue());
            //JRA-15723: Use the comments updated time for the updated time of the issue.  This allows users to
            // import old comments (via Jelly for example) without setting the updated time on the issue to now, but to the date
            // of the old comments.
            mutableIssue.setUpdated(new Timestamp(comment.getUpdated().getTime()));
            issue.store();
        }
        // Dispatch an event if required
        if (dispatchEvent)
        {
            dispatchEvent(EventType.ISSUE_COMMENTED_ID, comment, EasyMap.build("eventsource", IssueEventSource.ACTION));
        }
        return comment;
    }
More Specifically:
        if (tweakIssueUpdateDate)
        {
            IssueFactory issueFactory = ComponentAccessor.getComponentOfType(IssueFactory.class);
            MutableIssue mutableIssue = issueFactory.getIssue(issue.getGenericValue());
            //JRA-15723: Use the comments updated time for the updated time of the issue.  This allows users to
            // import old comments (via Jelly for example) without setting the updated time on the issue to now, but to the date
            // of the old comments.
            mutableIssue.setUpdated(new Timestamp(comment.getUpdated().getTime()));
            issue.store();
        }
Which seems to state that, if true, JIRA gets the date from the comment that is being added and makes it the update date for the issue.
Conclusion:
On CommentManager.java, it is stated that setting tweakIssueUpdateDate to true would make JIRA use the current date/time as the update date for the issue. However, on DefaultCommentManager.java it seems that , if tweakIssueUpdateDate is true, JIRA gets the date from the comment that is being added and makes it the update date for the issue instead.
Proposed Solution:
Change the following part:
        if (tweakIssueUpdateDate)
        {
            IssueFactory issueFactory = ComponentAccessor.getComponentOfType(IssueFactory.class);
            MutableIssue mutableIssue = issueFactory.getIssue(issue.getGenericValue());
            //JRA-15723: Use the comments updated time for the updated time of the issue.  This allows users to
            // import old comments (via Jelly for example) without setting the updated time on the issue to now, but to the date
            // of the old comments.
            mutableIssue.setUpdated(new Timestamp(comment.getUpdated().getTime()));
            issue.store();
        }
to
        if (!tweakIssueUpdateDate)
        {
            IssueFactory issueFactory = ComponentAccessor.getComponentOfType(IssueFactory.class);
            MutableIssue mutableIssue = issueFactory.getIssue(issue.getGenericValue());
            //JRA-15723: Use the comments updated time for the updated time of the issue.  This allows users to
            // import old comments (via Jelly for example) without setting the updated time on the issue to now, but to the date
            // of the old comments.
            mutableIssue.setUpdated(new Timestamp(comment.getUpdated().getTime()));
            issue.store();
        }
Workaround:
Instead of setting 'true' when calling the constructor, set false instead so it doesn't enter the loop.
- relates to
- 
                    JRASERVER-15723 Jelly AddComment tag changes the "updated" issue timestamp to execution script timestamp -         
- Closed
 
-