К старту курса о разработке на Java делимся переводом вводной статьи о Quarkus — "родной" для Kubernetes Java-платформе для создания высокопроизводительных веб-, бессерверных (serverless) и нативных приложений (оптимизированных для используемых микропроцессоров). В ней используются предварительная компиляция AOT и агрессивная оптимизация, например сканирование путей к классам, перезагрузка конфигурации и предварительная конфигурация самозагрузки приложения в процессе сборки. Результатом становится впечатляющая скорость загрузки. Другими словами, приложения, созданные с Quarkus, запускаются не просто быстро, а очень быстро!
Так же как для платформ Spring и Micronaut, в Quarkus можно использовать преимущество GraalVM для преобразования JVM-приложений в нативные исполняемые файлы, что ещё больше повышает их быстродействие.
Такой прирост производительности позволяет этой Java-платформе конкурировать с бессерверными, облачными и созданными на основе Kubernetes средами, создавая приложения Supersonic Subatomic Java. В Quarkus используются стандарты Java (такие, как MicroProfile, JAX-RS), а также лучшие из существующих Java-библиотек (например, Hibernate и Vert.x). Есть даже поддержка аннотаций Spring.
Quarkus + JHipster = простое ускорение Java
История технологий разработки наглядно демонстрирует, что совместить различные компоненты бывает очень непросто. Разработчики любят, когда им предлагается что-то авторитетно-одобренное, и как раз здесь на сцену выходит JHipster.
JHipster — это сопровождаемая сообществом разработчиков полнофункциональная платформа разработки, позволяющая создавать, развивать и развёртывать веб-приложения и ориентированные на микросервисы архитектуры. Стандартной серверной платформой в JHipster является Spring Boot, но постоянно появляются всё новые и новые возможности. Одним из таких вариантов стала blueprint-схема JHipster Quarkus.
Помимо прочего, одной из ключевых возможностей, определяющих успех JHipster, стала его расширяемость с помощью blueprint-схем. Blueprint-схема действует как плагин JHipster и позволяет вам переопределять стандартное поведение, настраивая его «на свой вкус».
Например, blueprint-схема Kotlin с JHipster является популярным дополнением, которое любят использовать разработчики. Использование blueprint-схемам многократно расширяет границы возможностей. Вот почему в JHipster есть даже реализации без Java (такие, как Node + NestJS и .NET Core). Эта публикация познакомит вас с основными шагами по использованию JHipster, blueprint-схемой Quarkus, а также протоколом OAuth для создания оптимизированного для работы на конкретных микропроцессорах и безопасного полнофункционального приложения.
Создание Java-приложения с Quarkus
Прежде чем приступить к работе, необходимо установить несколько инструментов.
Предварительные требования:
Установите JHipster и его blueprint-схему Quarkus, используя npm:
# Install JHipster globally
npm install -g generator-jhipster@6.10.5
# Install the JHipster Quarkus blueprint
npm install -g generator-jhipster-quarkus@1.1.1
Команда jhipster-quarkus — сокращение для jhipster --blueprints quarkus. Посмотреть все варианты её синтаксиса можно с помощью команды --help.
$ jhipster-quarkus --help
Создание приложения в среде JHipster Quarkus
mkdir okta-jhipster-quarkus-example && cd okta-jhipster-quarkus-example
# oh-my-zsh users: take okta-jhipster-quarkus-example
Чтобы запустить мастер создания приложений, можно выполнить команду jhipster-quarkus:
jhipster-quarkus
В этой вводной статье основным вопросом будет выполнение аутентификации.
Среда JHipster Quarkus позволяет использовать JWT (с возможностью управления пользователями в базе данных приложений) или аутентификацию OAuth 2.0/OIDC с применением поставщиков идентификационной информации, таких как Keycloak и Okta. OIDC расшифровывается как OpenID Connect, этот протокол представляет собой «тонкий слой» поверх протокола аутентификации OAuth 2.0. Его основная задача — обеспечить аутентификацию и идентификацию пользователя.
Ниже представлен пример ответов на вопросы мастера создания приложений.
После того как вы ответите на все эти вопросы, JHipster создаст код вашего приложения и выполнит команду npm install.
{
"generator-jhipster": {
"promptValues": {
"packageName": "com.mycompany.myapp",
"nativeLanguage": "en"
},
"jhipsterVersion": "6.10.5",
"applicationType": "monolith",
"baseName": "jhipster",
"packageName": "com.mycompany.myapp",
"packageFolder": "com/mycompany/myapp",
"serverPort": "8080",
"authenticationType": "oauth2",
"cacheProvider": "no",
"enableHibernateCache": true,
"websocket": false,
"databaseType": "sql",
"devDatabaseType": "h2Disk",
"prodDatabaseType": "mysql",
"messageBroker": false,
"buildTool": "maven",
"embeddableLaunchScript": false,
"useSass": true,
"clientPackageManager": "npm",
"clientFramework": "angularX",
"clientTheme": "none",
"clientThemeVariant": "",
"creationTimestamp": 1614834465776,
"jhiPrefix": "jhi",
"entitySuffix": "",
"dtoSuffix": "DTO",
"otherModules": [
{
"name": "generator-jhipster-quarkus",
"version": "1.1.1"
}
],
"enableTranslation": true,
"nativeLanguage": "en",
"languages": ["en"],
"blueprints": [
{
"name": "generator-jhipster-quarkus",
"version": "1.1.1"
}
]
}
}
В этом файле содержатся все ответы на исходные вопросы мастера JHipster, что позволит создать приложение без дополнительных запросов.
Убедитесь, что выполняемая с помощью Keycloak аутентификация OAuth 2.0/OIDC действительно работает
Помимо прочих файлов JHipster Quarkus создаёт файлы для инструментального средства Docker Compose, помогающие загрузить среду разработки, настроенную для вашего только что созданного приложения. При этом даже выполняется импорт данных Keycloak, заданных по умолчанию для пользователей и приложений, и вам не придётся делать это самим.
https://gitlab.webant.ru/russia_quiz/frontend/-/merge_requests
Если Keycloak запущен и работает, вы сможете выполнить вход в систему. Запустите ваше приложение с помощью Maven:
./mvnw
Вы можете видеть, что приложение запускается за 3,351 с, также выводится обширный список расширений Quarkus (включая oidc). Перейдите по адресу http://localhost:8080 в предпочитаемом вами браузере и нажмите ссылку sign in (вход).
Вы будете перенаправлены в Keycloak для входа в систему. При запросе идентификационных данных введите admin/admin.
После успешного прохождения аутентификации вы будете перенаправлены обратно в ваше приложение Quarkus.
Как работает поддержка протокола аутентификации OAuth 2.0 в JHipster Quarkus
Одной из проблем при разработке blueprint-схем JHipster, таких как Quarkus, является необходимость найти правильный баланс между повторным использованием существующих механизмов и добавлением индивидуальных реализаций.
С самого первого дня своего появления JHipster осуществлял интеграцию всех современных платформ для создания веб-приложений (Angular, React или даже Vue.js), совмещая их с фактически стандартными Java-технологиями, такими как Spring Boot и Spring Cloud.
В реализации JHipster Quarkus OAuth 2.0 за основу взято URI-перенаправление login/oauth2/code/oidc, предполагающее использование платформы аутентификации Spring Security. Настоятельно рекомендуем выполнять аутентификации на стороне сервера, поскольку это намного безопаснее (так как у браузера нет необходимости управлять какими-либо идентификационными данными и хранить какие-либо маркеры доступа).
В среде JHipster Quarkus, чтобы повторно использовать без изменений клиентские приложения и реализовать на серверной стороне механизм аутентификации по протоколу OAuth 2.0, в бэкенде должны быть открыты два HTTP-маршрута. Вот почему в JHipster Quarkus предусмотрен контроллер UserOauth2Controller и настраиваемые свойства Quarkus OIDC, позволяющие обеспечить правильную работу всего механизма.
Это своего рода интеграционная ловушка, на которую разработчики не хотят тратить время. Коллективный разум сообщества JHipster, объединяющий мнения самых эффективных разработчиков, объясняет высокую популярность и качество данной платформы.
Объединение JHipster Quarkus с сервисом Okta
Из этого раздела вы узнаете, как использовать сервис Okta в качестве провайдера протокола аутентификации OAuth 2.0/OIDC. В Okta предусмотрены два варианта для конфигурирования OIDC-приложения. Это можно выполнить либо в консоли разработчика, либо с помощью инфраструктуры Okta CLI.
Использование инфраструктуры Okta CLI для конфигурирования JHipster
Инфраструктура Okta CLI автоматизирует для вас все конфигурации JHipster и Okta. Для установки Okta CLI можно воспользоваться популярными менеджерами пакетов.
macOS (с помощью Homebrew):
brew install --cask oktadeveloper/tap/okta
Linux (с помощью Flatpak):
# Add Flathub repo
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
# install the package
flatpak install com.okta.developer.CLI
# add this to your appropriate dot file
alias okta="flatpak run com.okta.developer.CLI"
Windows (с помощью Chocolatey):
choco install okta -version 0.8.0
Вы также можете просто передать его в оболочку bash:
curl https://raw.githubusercontent.com/okta/okta-cli/master/cli/src/main/scripts/install.sh | bash
Если у вас ещё нет аккаунта разработчика в Okta, откройте терминал, перейдите в каталог приложения Quarkus и выполните okta register. Если у вас есть аккаунт, выполните okta login.
$ okta register
First name: Daniel
Last name: Petisme
Email address: daniel.petisme@gmail.com
Company: Okta
Creating new Okta Organization, this may take a minute:
OrgUrl: https://dev-9323263.okta.com
An email has been sent to you with a verification code.
Check your email
Verification code: 232819
New Okta Account created!
Your Okta Domain: https://dev-9323263.okta.com
To set your password open this link:
https://dev-9323263.okta.com/welcome/drpt2SjbRAPR-gvVHhnm
Если у вас уже есть аккаунт разработчика Okta, выполните команду okta login. Затем из каталога приложения Quarkus выполните okta apps create jhipster. Примите предлагаемые по умолчанию предложения для перенаправления URI.
$ okta apps create jhipster
Application name [okta-jhipster-quarkus-example]:
Redirect URI
Common defaults:
Spring Security - http://localhost:8080/login/oauth2/code/okta
Quarkus OIDC - http://localhost:8080/callback
JHipster - http://localhost:8080/login/oauth2/code/oidc
Enter your Redirect URI(s) [http://localhost:8080/login/oauth2/code/oidc, http://localhost:8761/login/oauth2/code/oidc]:
Enter your Post Logout Redirect URI(s) [http://localhost:8080/, http://localhost:8761/]:
Configuring a new OIDC Application, almost done:
Created OIDC application, client-id: 0oa5ozjxyNQPPbKc65d6
Creating Authorization Server claim 'groups':
Adding user daniel.petisme@gmail.com to groups: [ROLE_USER, ROLE_ADMIN]
Creating group: ROLE_USER
Creating group: ROLE_ADMIN
Конфигурация приложения Okta записывается здесь: /Users/daniel/workspace/okta-jhipster-quarkus-example/.okta.env
ПРИМЕЧАНИЕ: идентификаторы URI, перенаправленные http://localhost:8761*, предназначены для реестра JHipster, который часто используется при создании микросервисов с помощью JHipster. В инфраструктуре Okta CLI они добавляются по умолчанию. Они не требуются для приложения, создаваемого в этой вводной статье, но если их оставить, то никакого вреда точно не будет.
Инфраструктура Okta CLI создаст файл .okta.env в текущем каталоге. Если посмотреть на него, то вы увидите, что в нём содержатся несколько ключей и значений, предназначенных для протокола OIDC.
$ cat .okta.env
export QUARKUS_OIDC_AUTH_SERVER_URL="https://dev-9323263.okta.com/oauth2/default"
export QUARKUS_OIDC_CLIENT_ID="0oa5ozjxyNQPPbKc65d6"
export QUARKUS_OIDC_CREDENTIALS_SECRET="KEJ0oNOTFEUEFHP7i1TELLING1xLm1XPRn"
export QUARKUS_OIDC_AUTHENTICATION_REDIRECT_PATH="/login/oauth2/code/oidc"
export JHIPSTER_OIDC_LOGOUT_URL="https://dev-9323263.okta.com/oauth2/default/v1/logout"
Установите файл, чтобы задать переменные среды, и запустите ваше приложение с помощью Maven.
source .okta.env
./mvnw
Обязательно добавьте \*.env в ваш файл .gitignore, чтобы в коммиты не попадал ваш секрет клиента.
Как только приложение будет запущено, в окне в режиме инкогнито откройте http://localhost:8080 и выполните вход. Вам будет предложено ввести свои идентификационные данные Okta.
После успешного прохождения аутентификации вы будете перенаправлены обратно в ваше приложение. На начальной странице должен отображаться ваш адрес электронной почты.
Инфраструктура Okta CLI упрощает конфигурирование JHipster и выполняет следующие полезные операции.
Создаётся приложение OIDC с правильным перенаправлением URI.
Заводятся группы ROLE_ADMIN и ROLE_USER, требуемые для JHipster.
Ваш текущий пользователь добавляется в группы ROLE_ADMIN и ROLE_USER.
Создаётся заявка на группы на заданном по умолчанию сервере авторизации, и к ней добавляются эти пользовательские группы.
Но вдруг вы не любите работать из командной строки? Не паникуйте, тут есть кому прикрыть вашу спину! Инфраструктура Okta CLI проста в использовании, но для тех, кому это необходимо, есть возможность выполнить настройки с помощью интерфейса пользователя. Именно поэтому я так подробно рассматриваю каждый шаг по настройке приложения OIDC, работающего с JHipster Quarkus.
Использование консоли разработчика Okta для настройки JHipster
Если у вас нет аккаунта разработчика Okta, необходимо нажать ссылку sign up (вход). Тут нет ничего сверхсложного: просто укажите имя, фамилию, адрес электронной почты, выберите надёжный пароль и всё — вы готовы двигаться дальше. Выполнив вход в систему, вы попадаете в консоль разработчика:
Разверните вложенное меню Applications (Приложения) на панели навигации слева, затем выберите в меню Applications > Create App Integration (Приложения > Создать интеграцию приложений), чтобы запустить мастер создания приложений.
Выберите OIDC и Web Application. Затем нажмите кнопку Next (Далее).
Теперь вам необходимо будет указать некоторые настройки для приложения.
Name (Имя): можете указать любое имя на свой вкус, но разве «JHipster Quarkus» чем-то не подходит?
Login redirect URIs (Перенаправление URI при входе): определяет, будет ли Okta выполнять перенаправление в браузере клиента после аутентификации. Установите для него http://localhost:8080/login/oauth2/code/oidc, именно это значение настроено по умолчанию.
Logout redirect URIs (Перенаправление URI при выходе): http://localhost:8080 — указывается, куда будет перенаправляться пользователь после выполнения выхода.
Group assignments (Назначения групп): определяет, какие группы могут использовать это приложение.
Используйте предлагаемые значения по умолчанию для всех остальных настроек. Завершив ввод требуемых настроек для своего приложения, нажмите Save (Сохранить). На экране отобразятся подробные сведения о вашем приложении.
Наиболее важными являются следующие значения:
идентификационные данные клиента (ID и секрет клиента). Они позволяют приложению Java выполнять аутентификацию в сервисах Okta для последующей обработки потоков аутентификации и авторизации пользователей;
домен Okta, из которого Quarkus будет выводить конечные точки адресов URL для протоколов OAuth/OIDC.
Создание групп пользователей
Теперь настало время для создания групп пользователей. По умолчанию для JHipster требуются две следующие группы:
ROLE_USER: для аутентифицированных пользователей;
ROLE_ADMIN: для аутентифицированных пользователей с административными правами для этого приложения.
В консоли разработчика выберите в меню Directory > Groups (Каталог > Группы). Нажмите Add Group (Добавить группу) и создайте группу ROLE_ADMIN
Теперь добавьте группу ROLE_USER.
Всё, вы завершили создание групп, теперь займёмся добавлением пользователей.
Создание пользователей
Чтобы увидеть различие между обычными и административным пользователями, создайте пользователей в каждой из групп. Используя консоль разработчика Okta, выберите в меню Directory > People (Каталог > Люди). Нажмите Add Person (Добавить человека). Начните с создания пользователя Administrator.
Основным моментом тут является привязка пользователя Administrator к группе ROLE_ADMIN. Чтобы определить исходный пароль, который пользователь должен будет изменить, исключительно в демонстрационных целях для данной вводной статьи использована стратегию выбора пароля Set by Admin (Задаётся администратором). В реальном проекте я рекомендую использовать стратегию Set by User (Задаётся пользователем) с активацией по электронной почте. Теперь добавим обычного пользователя.
Убедитесь, что пользователь User входит в группу ROLE_USER. Очень важно использовать действующий адрес электронной почты, так как он может понадобиться при восстановлении пароля. Выберите в меню Applications > JHipster Quarkus (Приложения > JHipster Quarkus) и нажмите Assignments (Назначения). Назначьте группам пользователей, которых только что создали.
Добавление заявки на группы к маркеру ID
Последнее, о чём необходимо вам позаботиться, — это настроить заявку на группы, включающую группы пользователей в маркер ID. Выберите в меню Security > API (Безопасность > API), а затем нажмите default (по умолчанию). Щёлкните Claims > Add Claim (Заявки > Добавить заявку). Введите следующие значения:
Name (Имя): groups (группы);
Include in token type (Включить тип маркера): ID Token (Маркер ID);
Value type (Тип значения): groups (группы);
Filter (Фильтр): Matches regex with a value of .* (Соответствует регулярному выражению со значением .*).
Нажмите Create (Создать). Конфигурация Okta для JHipster готова!
Настройка Quarkus OIDC для Okta
В этот момент необходимо, чтобы приложение JHipster Quarkus уже было запущено и для использования Keycloak в качестве провайдера идентификационных данных для него. Давайте изменим настройки для работы с Okta. Во-первых, необходимо выйти из веб-приложения JHipster, чтобы предотвратить конфликт файлов cookie. Выберите Account > Sign Out (Аккаунт > Выход).
ПРИМЕЧАНИЕ: можно оставить приложение запущенным. Quarkus поддерживает работу в так называемом режиме для разработки (Dev Mode), обеспечивающем «горячую» перезагрузку любых исходных или ресурсных файлов при каждом их обновлении. Это исключительно удобно!
Откройте для редактирования файл src/main/resources/application.properties и найдите в нём раздел со следующей конфигурацией OIDC.
# OAuth 2.0 and OIDC
quarkus.oidc.enabled=true
quarkus.oidc.auth-server-url=http://localhost:9080/auth/realms/jhipster/
%dev.quarkus.oidc.client-id=web_app
%dev.quarkus.oidc.credentials.secret=web_app
quarkus.oidc.application-type=hybrid
quarkus.oidc.authentication.scopes=profile,address,email,address,phone,offline_access
quarkus.oidc.authentication.cookie-path=/
quarkus.oidc.authentication.redirect-path=/login/oauth2/code/oidc
quarkus.oidc.authentication.restore-path-after-redirect=false
jhipster.oidc.logout-url=http://localhost:9080/auth/realms/jhipster/protocol/openid-connect/logout
%test.quarkus.oidc.client-id=dummy
%test.quarkus.oidc.application-type=service
%test.jhipster.oidc.logout-url=some-dummy-logoutUrl
Показанные выше значения предназначены для Keycloak. Вами необходимо обновить следующие свойства, чтобы интегрировать своё приложение с Okta;
quarkus.oidc.auth-server-url: корневой URL для API Okta, полученный из домена приложения OIDC;
quarkus.oidc.client-id: ID клиента для приложения OIDC;
quarkus.oidc.credentials.secret: секрет клиента для приложения OIDC;
jhipster.oidc.logout-url: в JHipster браузер будет запускать выход из системы. Серверная сторона должна предоставлять эту информацию (пока её невозможно получить с помощью OIDC-поиска).
После того как вы обновите этот файл, ваши настройки должны выглядеть примерно так:
# OAuth 2.0 and OIDC
quarkus.oidc.enabled=true
quarkus.oidc.auth-server-url=https://dev-9323263.okta.com/oauth2/default
quarkus.oidc.client-id=0oaajhdr9q9jxbBM95d6
quarkus.oidc.credentials.secret=NEVERSHOWSECRETS
quarkus.oidc.application-type=hybrid
quarkus.oidc.authentication.scopes=profile,address,email,address,phone
quarkus.oidc.authentication.cookie-path=/
quarkus.oidc.authentication.redirect-path=/login/oauth2/code/oidc
quarkus.oidc.authentication.restore-path-after-redirect=false
jhipster.oidc.logout-url=https://dev-9323263.okta.com/oauth2/default/v1/logout
Перезапустите приложение, перейдите по адресу http://localhost:8080. Нажмите sign in (вход) и вы будете перенаправлены на страницу входа Okta.
Введите admin в качестве имени пользователя и пароль, который вы задали. Okta определит, что это ваш первый вход в систему, и предложит сменить пароль. После выполнения вы будете перенаправлены в ваше приложение Quarkus.
Переход в нативный формат с помощью Quarkus и GraalVM
Заключительным шагом в данной вводной статье будет упаковка приложения Java в виде нативного выполняемого файла (оптимизированного для используемого микропроцессора). И снова JHipster надёжно прикрывает ваши тылы, делая для вас всё необходимое. Просто выполните в Maven команду package с профилем native:
./mvnw package -Pnative -DskipTests
Вы знаете, мы знаем, все знают: мы пропустили этап тестирования — в этом демонстрационном примере всё работает идеально. Но, пожалуйста, никогда не пропускайте тестирование в условиях реальной промышленной разработки. Если в используемый вами JDK не включён GraalVM, вы получите ошибку:
[error]: Build step io.quarkus.deployment.pkg.steps.NativeImageBuildStep#build threw an
exception: java.lang.RuntimeException: Cannot find the `native-image` in the
GRAALVM_HOME, JAVA_HOME and System PATH. Install it using `gu install native-image`
Самым простым способом решения этой проблемы будет применение SDKMAN для установки Java 11 с GraalVM:
sdk install java 21.0.0.2.r11-grl
Затем выполните gu install native-image:
$ gu install native-image
Downloading: Component catalog from www.graalvm.org
Processing Component: Native Image
Downloading: Component native-image: Native Image from github.com
Installing new component: Native Image (org.graalvm.native-image, version 21.0.0.2)
Как только процесс завершится, перезапустите команду package в Maven:
./mvnw package -Pnative -DskipTests
На нативную компиляцию требуется немало времени. У вас может возникнуть желание прогуляться, выпить чашку-другую кофе или несколько раз отжаться. Но, если вы предпочитаете остаться за компьютером, можно потратить время на следующее:
ознакомиться с проектом JHipster Quarkus Blueprint;
исследовать сайт для разработчиков Okta;
изучить эти великолепные руководства по Quarkus.
Спустя примерно три минуты нативный выполняемый файл должен быть готов:
Запустите его как нативный выполняемый файл, используя команду target/*runner:
Ваше старое доброе Java-приложение запустится через 1 секунду! Помните, я рассказывал о приросте памяти? Ниже привожу команду, как посмотреть потребление памяти в мегабайтах:
$ ps -o pid,rss,command | grep --color jhipster | awk '{$2=int($2/1024)"M";}{ print;}'
30951 46M ./target/jhipster-1.0.0-SNAPSHOT-runner
31433 0M grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn --color jhipster
Ваше приложение потребляет менее 50 МБ памяти. Перейдите по адресу http://localhost:8080 и убедитесь, что всё исправно работает. Теперь наслаждайтесь своим успехом!
Дальнейшая разработка с помощью JHipster Quarkus
Надеюсь, вы получили удовольствие от данной вводной статьи, пройдя все этапы создания нативного приложения и применяя для этого Java, Quarkus и JHipster. Не правда ли, впечатляет, как JHipster и Okta CLI делают для вас основную тяжёлую работу?! Вы можете найти пример, созданный в этой вводной статье, на GitHub. Если вы заинтересованы в дополнительном изучении blueprint-схем Quarkus, посмотрите проект generator-jhipster-quarkus, также размещённый на GitHub.
Совсем недавно Java считали медленным языком программирования, а вернее было бы сказать, что медленной была виртуальная машина Java, но это не помешало языку стать одним из самых востребованных по версии TIOBE. Сегодня Java становится всё быстрее, а это значит, что она ещё надолго сохранит способность конкурировать с новыми языками; кроме того, в последнее время наметилась тенденция к упрощению синтаксиса Java. Если вам интересен этот язык и работа с ним в перспективе, то вы можете посмотреть на программу обучения нашего курса по Java, где студенты за 14 месяцев получают всестороннюю подготовку к трудоустройству в качестве Java-разработчика.
Узнайте, как прокачаться и в других специальностях или освоить их с нуля:
Другие профессии и курсы
ПРОФЕССИИ
КУРСЫ
mrise
Самым ужасным в JHipster-е является то, что этот «генератор микросервисов» не умеет делать uuid-ы первичными ключами. Религия разработчиков не позволяет.