Прощай, Grails. Привет, Micronaut
Всего в цикле публикаций о миграции из Grails в Micronaut будет 10 частей:
Многомодульный проект
Конфигурация
Статическая компиляция
Датасеты
Маршалинг
Классы предметной области
Сервисы
Контроллеры
Приложение Micronaut
Micronaut Data
Обратите внимание: ваше приложение должно быть создано в Grails 4.x или более поздней версии.
Часть 1. Многомодульный проект
Мы начинаем цикл статей с инструкциями, которые помогут вам шаг за шагом мигрировать из Grails. Итак, для начала нужно извлечь компоненты вашего приложения в отдельные библиотеки. Это лучше всего сделать путем создания многомодульного проекта (в документации Gradle — multi-project). Чтобы создать структуру, которую будет легко масштабировать, мы воспользуемся набором плагинов Kordamp Gradle.
Сперва перенесем все, что имеет отношение к вашему приложению, в отдельную папку apps/<имя-вашего-приложения>
. Далее во всех инструкциях этого цикла мы будем писать hello
там, где должно быть имя вашего приложения. Таким образом, у нас получится новый путь apps/hello
. Файлы Gradle перемещать не нужно, за исключением файла build.gradle
(ему следует присвоить имя, совпадающее с именем папки, в которую он перемещен; в нашем примере — hello.gradle
). Файлы Grails Wrapper можно удалить.
├── .gitignore
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── grails-app
├── grails-wrapper.jar
├── grailsw
├── grailsw.bat
└── src
Вот так будет выглядеть структура папок в проекте после перемещения всех файлов:
├── .gitignore
├── apps
│ └── hello
│ ├── grails-app
│ ├── hello.gradle
│ └── src
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
└── gradlew.bat
Далее создаем файл setting.gradle
, с помощью которого будут установлены плагины Kordamp Gradle:
buildscript {
repositories {
gradlePluginPortal()
}
dependencies {
classpath 'org.kordamp.gradle:settings-gradle-plugin:0.46.0'
}
}
apply plugin: 'org.kordamp.gradle.settings'
rootProject.name = 'hello-root'
projects {
directories = ['apps', 'libs']
}
В переменной rootProject.name
следует объявить название проекта, добавив -root
, чтобы избежать конфликта имен. Благодаря плагинам Kordamp Gradle все подпапки внутри папок app
и libs
автоматически определятся как подпроекты.
Теперь создаем новый файл build.gradle
в корневой папке. Меняем значения на свои:
plugins {
id 'org.kordamp.gradle.groovy-project' version '0.46.0'
}
config {
release = (rootProject.findProperty('release') ?: false).toBoolean()
info {
name = 'Sample'
vendor = 'Acme'
description = 'Sample project'
links {
website = 'https://github.com/me/repo'
issueTracker = 'https://github.com/me/repo/issues'
scm = 'https://github.com/me/repo.git'
}
people {
person {
id = 'joecool'
name = 'Joe Cool'
roles = ['developer']
}
}
}
licensing {
enabled = false
}
}
allprojects {
repositories {
mavenCentral()
}
}
Наконец необходимо явно объявить класс приложения (в нашем примере — hello.Application
) в подпроекте apps/hello/hello.gradle
, иначе произойдет конфликт конфигурации плагинов Gradle и приложение не запустится:
springBoot {
mainClassName = 'hello.Application'
}
Теперь пробуем запустить приложение с помощью команды ниже, чтобы проверить, все ли в порядке:
./gradlew bootRun
Следующий шаг — перенос конфигурации из Grails в объекты конфигурации Micronaut.
Часть 2. Конфигурация
Продолжаем плавно мигрировать из Grails: теперь разберемся с доступом к конфигурации.
В Grails можно получить доступ к файлам конфигурации из объекта GrailsApplication
или с помощью статических методов класса Holders
.
@CompileDynamic
class MyService {
GrailsApplication grailsApplication
String returnFoo() {
// normal access
return grailsApplication.config.agorapulse.foo
}
String returnBar() {
// static access
return Holders.config.agorapulse.bar
}
}
Grails 4.x и старше уже поддерживает Micronaut, так что можно пользоваться возможностями последнего, в том числе взаимодействовать с объектами свойств конфигурации. Можно, например, создать простой объект для привязки значений конфигурации:
@CompileStatic
@ConfigurationProperties('agorapulse')
class AgorapulseConfiguration {
String foo
String bar
}
Этот объект можно интегрировать в любой сервис Grail. К полю нужно добавить аннотацию @Inject
, так как автоматическая привязка для бинов Micronaut уже не работает.
@CompileStatic
class MyService {
@Inject AgorapulseConfiguration configuration
String returnFoo() {
return configuration.foo
}
String returnBar() {
return configuration.bar
}
}
Не лишним также будет добавить дополнительную проверку класса конфигурации. Теперь ваш сервис полностью готов к внедрению статической компиляции.
В следующей части мы расскажем, как реализовать статическую компиляцию для всего проекта Grails.
Часть 3. Статическая компиляция
Переход в другую экосистему — всегда непростая задача, даже если это родственный фреймворк. Чтобы миграция прошла успешно, стоит внедрить статическую компиляцию в качестве дополнительного уровня безопасности в масштабе приложения. Это также поможет на следующих этапах миграции при рефакторинге моделей предметной области. Процедура внедрения статической компиляции подробно описана в статье по ссылке ниже: рекомендуем сначала прочитать ее.
Мы хотим внедрить статическую компиляцию во все приложения и библиотеки проекта, поэтому обновляем файл settings.gradle
следующим образом:
projects {
directories = ['apps', 'libs']
plugins {
dirs(['apps', 'libs']) {
id 'groovy'
id 'java-library'
}
}
}
Эти строки гарантируют, что во всех подпроектах apps
и libs
будут работать плагины groovy
и java-library
.
Теперь для внедрения статической компиляции в масштабе приложения нужно настроить зависимость Enterprise Groovy. Дописываем этот код в файл build.gradle
:
projects {
subprojects {
dirs(['apps', 'libs']) {
// add Enterprise Groovy library
dependencies {
compileOnly 'com.virtualdogbert:enterprise-groovy:1.0.3'
}
// configure Enterprise Groovy library
compileGroovy.groovyOptions.configurationScript =
rootProject.file('config/groovy/conventions.groovy')
}
}
}
Создаем файл конфигурации, упомянутый выше, в папке config/groovy/conventions.groovy
:
Map conventions = [
disable : false,
whiteListScripts : true,
disableDynamicCompile : false,
dynamicCompileWhiteList : [
'UrlMappings',
'Application',
'BootStrap',
'resources',
'org.grails.cli'
],
limitCompileStaticExtensions: false,
defAllowed : false, // For controllers you can use Object in place of def, and in Domains add Closure to constraints/mappings closure fields.
skipDefaultPackage : true, // For GSP files
compileStaticExtensions : [
'org.grails.compiler.ValidateableTypeCheckingExtension',
'org.grails.compiler.NamedQueryTypeCheckingExtension',
'org.grails.compiler.HttpServletRequestTypeCheckingExtension',
'org.grails.compiler.WhereQueryTypeCheckingExtension',
'org.grails.compiler.DynamicFinderTypeCheckingExtension',
'org.grails.compiler.DomainMappingTypeCheckingExtension',
'org.grails.compiler.RelationshipManagementMethodTypeCheckingExtension'
],
]
System.setProperty(
'enterprise.groovy.conventions',
"conventions=${conventions.inspect()}"
)
Простые действия закончились, переходим к более сложным манипуляциям.
Даже если вы все делали верно на предыдущих шагах, вы можете столкнуться с ошибками компиляции при запуске команды ./gradlew classes
в терминале. У Enterprise Groovy есть один недостаток: результаты статической компиляции не отображаются в явном виде в IDE. Поэтому рекомендуем добавлять аннотации @CompileStatic
или @GrailsCompileStatic
к классам, которые не прошли компиляцию: так вы увидите все ошибки прямо в вашей среде разработки. Если какие-либо части кода не компилируются, добавьте к ним аннотацию @CompileDynamic
. Учтите, что динамическую компиляцию следует использовать в минимальном масштабе. Бонус: в результате код вашего приложения будет более устойчивым к ошибкам и будет меньше риска при его рефакторинге.
В следующей части мы будем готовить датасеты для классов предметной области. Они послужат основой для тестирования, которое мы будем проводить далее, чтобы гарантировать успешную миграцию.
Источники и обсуждение:
Оригинальные публикации: часть 1, часть 2, часть 3.
Материал подготовлен в рамках курса «Groovy Developer».
Всех желающих приглашаем на бесплатное demo-занятие «Знакомство с Micronaut». Micronaut представляет собой легковесный фреймворк на основе JVM для создания приложений на основе микросервисов. На занятии мы рассмотрим возможности фреймворка, такие как compile time DI, создание native image, serverless функции, и другие.
>> РЕГИСТРАЦИЯ