Вставка ссылки на сущность в тело письма

Jmix 2.2, плагин 2.3.

Есть задача, при изменении статуса сущности отправлять email пользователю, в котором, помимо шаблона, будет указана ссылка на экран деталей сущности (что-то вроде задания на согласование к примеру).

На этапе разработки программы можно зайти в неё через браузер либо через http://localhost:8090 либо через IP, к примеру http://192.192.192.192:8090. После окончания разработки соответственно программа задрейфует на неизвестный мне сервер.

Накидал шаблон в формате HTML (картинки, текст) и вставил с помощью библиотеки thymeleaf в него переменные, преобразовал в строку и добавил в EmailBuilder с помощью метода setBody(String body).

Сейчас ссылку на сущность я собирал вручную, с помощью ServletUriComponentBuilders.fromCurrentContextPath().toUriString() получил базовый url, дальше взял путь экрана деталей сущности из аннотации @Route(), дальше UUID сущности и ещё добавил строкой параметр ?mode=readOnly.

Получился составной Url, который, как я думал, позволит не зависеть от того, на какой конкретно сервере сейчас запущено приложение.

Но получилось странно, когда я заходил в приложение через браузер по строке localhost:8090, то и в электронном письме приходила ссылка с localhost, а когда заходил через ввод IP, то приходила ссылка с IP. Что будет если зайти с другого компьютера и отправить письмо, я пока не пробовал.

И ещё столкнулся с проблемой, что при открытии ссылки можно вручную стереть в адресной строке ?mode=readOnly и получить доступ к редактированию полей, в то время как открытии этого же экрана из приложения такой фокус не работает (при открытии через viewNavigators стоит .setReadOnly(true)).

Собственно вопрос, есть ли элегантный способ сделать нужную мне операцию встроенными средствами? Или нужно как-то доработать мой метод, чтобы избежать подобных проблем и сборка строки-ссылки не зависела ни от каких внешних факторов и производилась динамически каждый раз при отправке письма?

Добрый день.

Не совсем понимаю в чем проблема, что URL, который выдает ServletUriComponentBuilders совпадает с тем, что введено в адресной строки браузера.

Получить текущий URL можно еще следующим способом:

Page page = UI.getCurrent().getPage();
page.fetchCurrentURL(url -> {
    // ...
});

Но он так же вернет значение из адресной строки, да и сам код будет работать только там где доступен UI, т.е. говоря простыми словами, если пользователь сидит в нашем приложении (вкладка браузера и есть UI) и вызвал отправку письма. В остальных случаях URL нужно получать средствами Spring.

Относительный роут до экрана можно получить следующим кодом, чтобы не доставать роут из @Route аннотации:

String url = RouteConfiguration.forSessionScope().getUrl(UserDetailView.class, new RouteParameters("id", "123"));

Касательно возможности руками удалить ?mode=readonly, завел задачу на GitHub.

Глеб

Спасибо, полезная штука, воспользовался.

Потестируем пока такой способ, посмотрим как пойдёт.

По поводу readOnly пока в каждом экране деталей поставлю в слушателе onBeforeShow() вручную setReadOnly(true), т.к. редактировать обычные поля открытой сущности в UI пока не требуется, а ссылочные поля и так вроде получается редактировать через их экраны деталей и они сохраняются, если нажать кнопку “ОК”, а поля меняются в логике контроллера и сохраняются через dataManager.