[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-jira-kak-sozdat-rest-endpoint-v-plagine-jira-dc":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},924,"kak-sozdat-rest-endpoint-v-plagine-jira-dc",27,"jira","Jira","📋","Как создать REST-эндпоинт в плагине Jira DC?","REST-модуль плагина позволяет создавать API-эндпоинты, доступные по URL вида `\u002Frest\u002Fmyapi\u002F1.0\u002F...`, используя JAX-RS (Jersey).\n\n### Объявление в atlassian-plugin.xml\n\n```xml\n\u003Crest key=\"my-rest-api\" path=\"\u002Fmyapi\" version=\"1.0\">\n    \u003Cdescription>REST API моего плагина\u003C\u002Fdescription>\n\u003C\u002Frest>\n```\n\n### REST-ресурс\n\n\u003Cdetails>\n\u003Csummary>Код ConfigResource\u003C\u002Fsummary>\n\n```java\n@Path(\"\u002Fconfig\")\n@Consumes({MediaType.APPLICATION_JSON})\n@Produces({MediaType.APPLICATION_JSON})\n@Named\npublic class ConfigResource {\n\n    private final TaskConfigService configService;\n    private final JiraAuthenticationContext authContext;\n    private final PermissionManager permissionManager;\n\n    @Inject\n    public ConfigResource(TaskConfigService configService,\n                          @ComponentImport JiraAuthenticationContext authContext,\n                          @ComponentImport PermissionManager permissionManager) {\n        this.configService = configService;\n        this.authContext = authContext;\n        this.permissionManager = permissionManager;\n    }\n\n    @GET\n    @Path(\"\u002F{id}\")\n    public Response getConfig(@PathParam(\"id\") int id) {\n        ApplicationUser user = authContext.getLoggedInUser();\n        if (user == null) {\n            return Response.status(Response.Status.UNAUTHORIZED).build();\n        }\n\n        TaskConfig config = configService.getById(id);\n        if (config == null) {\n            return Response.status(Response.Status.NOT_FOUND)\n                    .entity(new ErrorResponse(\"Config not found\"))\n                    .build();\n        }\n\n        return Response.ok(ConfigDto.from(config)).build();\n    }\n\n    @POST\n    public Response createConfig(CreateConfigRequest request) {\n        ApplicationUser user = authContext.getLoggedInUser();\n        if (user == null) {\n            return Response.status(Response.Status.UNAUTHORIZED).build();\n        }\n\n        if (!permissionManager.hasPermission(GlobalPermissionKey.ADMINISTER, user)) {\n            return Response.status(Response.Status.FORBIDDEN)\n                    .entity(new ErrorResponse(\"Admin permission required\"))\n                    .build();\n        }\n\n        TaskConfig created = configService.create(\n                request.getProjectKey(), request.getConfiguration());\n\n        return Response.status(Response.Status.CREATED)\n                .entity(ConfigDto.from(created))\n                .build();\n    }\n\n    @DELETE\n    @Path(\"\u002F{id}\")\n    public Response deleteConfig(@PathParam(\"id\") int id) {\n        ApplicationUser user = authContext.getLoggedInUser();\n        if (!permissionManager.hasPermission(GlobalPermissionKey.ADMINISTER, user)) {\n            return Response.status(Response.Status.FORBIDDEN).build();\n        }\n\n        configService.delete(id);\n        return Response.noContent().build();\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\nURL для вызова: `GET https:\u002F\u002Fjira.company.com\u002Frest\u002Fmyapi\u002F1.0\u002Fconfig\u002F42`\n\n### Частые ошибки\n\n- Возвращение Entity (AO) напрямую вместо DTO — вызывает LazyLoading-ошибки и утечку данных\n- Забыть проверку прав — REST-эндпоинт доступен любому аутентифицированному пользователю\n- Использование `@Autowired` вместо `@Inject` в REST-ресурсе\n- CORS: Jira не добавляет CORS-заголовки по умолчанию — для внешних клиентов нужен servlet-filter\n\n### Как используется в 2026\n\n- REST-эндпоинты в плагинах — основной способ API-интеграции для DC\n- JAX-RS (Jersey) остаётся стандартом; переход на другие фреймворки невозможен из-за OSGi\n- Для CORS рекомендуется использовать Atlassian CORS Plugin или собственный фильтр\n\n> **На собеседовании:** покажите знание JAX-RS аннотаций (`@Path`, `@GET`, `@POST`, `@Consumes`, `@Produces`). Обязательно упомяните проверку аутентификации и авторизации в каждом эндпоинте — по умолчанию все эндпоинты требуют аутентификацию, `@AnonymousAllowed` — для открытых. Всегда возвращайте DTO, не AO-entity.","","middle",[15,16,17,7],"rest-api","jax-rs","jira-plugin",[],null,{"title":21,"description":22,"ogTitle":23,"ogDescription":24,"keywords":25,"schemaAnswer":35,"featuredSnippetReady":36},"Как создать REST-эндпоинт в плагине Jira DC — Gymterview","REST-модуль Jira DC плагина: JAX-RS (Jersey), @Path, аутентификация, авторизация, DTO, @AnonymousAllowed. Полный пример CRUD ресурса.","REST-эндпоинт в плагине Jira DC: JAX-RS, аутентификация, DTO — Gymterview","Как создать REST API в Jira DC плагине: JAX-RS аннотации, проверка прав, DTO вместо AO entity, CORS.",[26,27,28,29,30,31,32,33,34],"REST эндпоинт Jira","JAX-RS","Jersey","@Path","@GET","@POST","Jira DC plugin","REST API","Java","REST-модуль объявляется в atlassian-plugin.xml как \u003Crest path=\"\u002Fmyapi\" version=\"1.0\">. Ресурсы используют JAX-RS аннотации (@Path, @GET, @POST, @Consumes, @Produces). По умолчанию требуется аутентификация, @AnonymousAllowed — для открытых эндпоинтов. Всегда возвращайте DTO вместо AO entity. URL: \u002Frest\u002Fmyapi\u002F1.0\u002F...",true]