[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-jira-kak-sozdat-workflow-post-function-condition-validator":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":18,"progress":19,"seo":20},927,"kak-sozdat-workflow-post-function-condition-validator",27,"jira","Jira","📋","Как создать Workflow Post-Function, Condition, Validator?","Расширения workflow позволяют добавлять автоматическую логику при переходах между статусами в Jira: Post-Function выполняет действие после перехода, Condition определяет видимость перехода, Validator проверяет условия перед выполнением.\n\n### Post-Function\n\n\u003Cdetails>\n\u003Csummary>Код AutoAssignFunction и Factory\u003C\u002Fsummary>\n\n```xml\n\u003Cworkflow-function key=\"auto-assign-function\"\n                   class=\"com.example.plugin.workflow.AutoAssignFunctionFactory\">\n    \u003Cfunction-class>com.example.plugin.workflow.AutoAssignFunction\u003C\u002Ffunction-class>\n    \u003Corderable>true\u003C\u002Forderable>\n    \u003Cunique>false\u003C\u002Funique>\n    \u003Cresource name=\"view\" type=\"velocity\"\n              location=\"templates\u002Fworkflow\u002Fauto-assign-view.vm\"\u002F>\n    \u003Cresource name=\"input-parameters\" type=\"velocity\"\n              location=\"templates\u002Fworkflow\u002Fauto-assign-input.vm\"\u002F>\n\u003C\u002Fworkflow-function>\n```\n\n```java\npublic class AutoAssignFunction implements FunctionProvider {\n\n    private static final Logger log = LoggerFactory.getLogger(AutoAssignFunction.class);\n\n    @Override\n    public void execute(Map transientVars, Map args, PropertySet ps) {\n        MutableIssue issue = (MutableIssue) transientVars.get(\"issue\");\n        String groupName = (String) args.get(\"groupName\");\n\n        if (groupName == null || groupName.isEmpty()) {\n            log.warn(\"Имя группы не задано для AutoAssignFunction\");\n            return;\n        }\n\n        GroupManager groupManager = ComponentAccessor.getGroupManager();\n        Collection\u003CApplicationUser> members = groupManager.getUsersInGroup(groupName);\n\n        if (!members.isEmpty()) {\n            ApplicationUser assignee = members.iterator().next();\n            issue.setAssignee(assignee);\n            log.info(\"Задача {} назначена на {}\", issue.getKey(),\n                    assignee.getDisplayName());\n        }\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n### Condition\n\n```java\npublic class OnlyReporterCondition extends AbstractJiraCondition {\n\n    @Override\n    public boolean passesCondition(Map transientVars, Map args, PropertySet ps)\n            throws WorkflowException {\n        Issue issue = (Issue) transientVars.get(\"issue\");\n        ApplicationUser currentUser = getCallerUser(transientVars, args);\n\n        if (issue == null || currentUser == null) return false;\n        return currentUser.equals(issue.getReporter());\n    }\n}\n```\n\n### Validator\n\n```java\npublic class CommentRequiredValidator implements Validator {\n\n    @Override\n    public void validate(Map transientVars, Map args, PropertySet ps)\n            throws InvalidInputException, WorkflowException {\n\n        int minLength = Integer.parseInt(\n                (String) args.getOrDefault(\"minLength\", \"10\"));\n\n        IssueInputParameters inputParams =\n                (IssueInputParameters) transientVars.get(\"issueInputParameters\");\n        String comment = inputParams != null ? inputParams.getComment() : null;\n\n        if (comment == null || comment.trim().length() \u003C minLength) {\n            throw new InvalidInputException(\n                    \"Комментарий обязателен (минимум \" + minLength + \" символов)\");\n        }\n    }\n}\n```\n\n### Частые ошибки\n\n- Не вызвать `issue.store()` в Post-Function — изменения не сохраняются\n- Бросать RuntimeException в Condition — нужно возвращать false, а не падать\n- Тяжёлая логика в Condition — вызывается при каждом отображении задачи для определения доступных переходов\n- Порядок Post-Functions важен — встроенные функции Jira (Update Issue, Generate Events) должны идти после кастомных\n\n### Как используется в 2026\n\n- Workflow-расширения — одна из самых востребованных функций DC-плагинов\n- В Cloud аналог — Forge jira:workflowCondition, jira:workflowValidator, jira:workflowPostFunction\n- ScriptRunner покрывает около 80% типичных workflow-сценариев без написания Java-плагина\n\n> **На собеседовании:** чётко разграничьте три типа: Condition (видимость перехода), Validator (проверка перед), Post-Function (действие после). Factory-класс обязателен — он отвечает за UI конфигурации в admin-панели. В Condition нельзя бросать исключения — только возвращать boolean.","","senior",[15,16,17,7],"jira-workflow","workflow","jira-plugin",[],null,{"title":21,"description":22,"ogTitle":23,"ogDescription":24,"keywords":25,"schemaAnswer":33,"featuredSnippetReady":34},"Как создать Workflow Post-Function, Condition, Validator — Gymterview","Расширения workflow Jira DC: Post-Function (действие после перехода), Condition (видимость перехода), Validator (проверка перед). Factory-классы и Velocity.","Workflow расширения: Post-Function, Condition, Validator — Gymterview","Три типа расширений workflow Jira DC: Post-Function, Condition, Validator. Реализация, Factory-классы, типичные ошибки.",[26,27,28,29,30,31,32],"Workflow Post-Function","Workflow Condition","Workflow Validator","FunctionProvider","Jira workflow","Factory","Jira DC plugin","Три типа расширений workflow: Post-Function (FunctionProvider, действие после перехода — назначить, обновить поле), Condition (AbstractJiraCondition, видимость кнопки перехода — возвращает boolean), Validator (проверка перед переходом — бросает InvalidInputException). Factory-класс обязателен для UI конфигурации. В Condition нельзя бросать исключения. ScriptRunner покрывает ~80% сценариев без Java.",true]