Pull to refresh

Comments 6

Это ужасно от начала и до конца.

  1. Расковыривание JDK (в частности, tools.jar) и включение его частей в состав своего продукта — прямое нарушение лицензии.
  2. Подключить агента на лету — вопрос нескольких строк кода (см. jattach). У вас же сплошное шаманство вокруг рефлекшна и приватного API.
  3. В Java 9 системный класслоадер — уже не URLClassLoader, и поэтому всё это работать не будет.
  4. Instrumentation API — не единственный способ модификации классов. Можно сделать через JVMTI RedefineClasses, и тогда агенты вообще не нужны!
Я не отрицаю, что это ужасно — я говорю о том, что это возможно. Это просто результат исследования. Я никому не рекомендую это использовать в таком виде в боевых целях.

jattach — то что нужно! Видел же ваш доклад, где вы его показывали. Идея вместо плясок с загрузкой библиотек и ковыряния в JDK вызывать jattach при установке плагина мне определенно нравится. Если-таки придется это исследование довести, то попробую сделать так, спасибо!
Не уверен, что код вызова jattach при установке плагина, получится более элегантным, но думаю, это то что нужно.

Замечу, что основная доля шаманства связана с тем, чтобы функционал упихнуть в плагин и сделать некий «движок для трансформаций». Мы можем легко и быстро написать новую трансформацию на Java на высоком уровне с помощью ByteBuddy, который сделает за нас много полезной работы, собрать стандартный atlassian-plugin и поставить его в JIRA — и вот трансформация применилась.
Понятно, что желание «быстро написать новую трансформацию» — это не нормальное желание, но в контексте статьи, мы именно этого и добиваемся) В этом основная ценность моего решения
По этой же причине я не уверен, что хороший вариант — это использование RedefineClasses — тут для каждой трансформации нужно писать отдельный платформозависимый код.

Что касается, Java 9. Последние версии JIRA работают на Java 8, и по моему мнению будут работать на ней еще долгое время после выхода 9ки. Поэтому этот вопрос я не исследовал. Возможно, модуль загрузить будет даже проще
Я понимаю вашу задачу и ценю проделанную работу, но мне не очень нравится подход. Java разработчики привыкли, что с помощью Reflection и Unsafe можно сделать что угодно, и всячески это эксплуатируют. И я в том числе. Однако шумиха вокруг приватного API, Java 9 и модульности заставила меня всерьёз пересмотреть позицию. Если можно избегать хаков — лучше избегать. Тем более, что в вашем случае вроде как можно.

Если бы передо мной стояла подобная задача, я бы, пожалуй, сразу отказался от поддержки JRE-only окружения. Тогда через стандартный ToolProvider.getSystemToolClassLoader() мы получаем доступ к VirtualMachine и вызываем attach безо всяких хаков. Плюсы: 1) легальность; 2) публичный API; 3) только Java и никакой возни с нативными библиотеками.

Если же очень хочется на чистом JRE (впрочем, тех, кому фича действительно нужна, не затруднит и JDK поставить), то без натива не обойтись: будь то attach.dll, jattach или собственная JVMTI библиотека. Причём последний вариант самый простой, т. к. не требует знания PID и подключения агентов. Поэтому не понятно, чем вам JVMTI не угодил — нативная библиотека может точно так же применять любые переданные из Java трансформации. Собственно, Instrumentation API через него и работает. Кстати, если будут вопросы по jattach или JVMTI — всегда готов помочь.
JIRA имеет API для расширения как самого приложения, так и расширения поведения workflow.

В первом случае можно просто создать кастомный CustomField, и реализовать в нем комплексную валидацию.
Во втором случае мы имеем достаточный функционал для контроля всего жизненного цикла тикетов: триггеры, обработчики событий, превалидация форм, пост-функции workflow.

В оправдание вашего костыльного метода можно сказать, что JIRA и ее компоненты имеют отвратительную документацию, и, зачастую, устаревшую, если вы используете последнюю на данный момент версию (7.x).
Увы, JIRA как платформа по поддержке workflow не идеально поддерживает связь workflow и изменения значений полей.
Применяя ваш подход к моему примеру с назначением на группу:
  • в первом случае мы либо отказываемся от использования системного поля Assignee, что нехорошо, потому что под него много чего в системе уже написано полезного; либо будем вынуждены обновлять/откатывать значение assignee при ошибке валидации уже после обновления в отдельной транзакции, что тоже нехорошо, т.к. можем поломать консистентность данных ишью между транзакциями. Точки входа, где мы могли бы провалидировать значения всех полей внутри одной транзакции обновления, у нас нет.
  • во втором случае изменение поля Assignee не вызывает перехода по workflow, а это значит ни один workflow валидатор или постфункция вызвана не будут
Sign up to leave a comment.

Articles