null

Полезные Maven/Gradle плагины для Liferay разработки

Разработка  корпоративных решений и интранет-порталов на базе Liferay требует управления сложной экосистемой, включая инициализацию серверов приложений, сборку различных модулей, работу с базой данных и REST-эндпоинтами. Чтобы ускорить разработку, Liferay предоставляет специализированный инструментарий в форме плагинов для популярных систем сборки, таких как Gradle и Maven. В этой заметке мы представим краткий обзор некоторых таких плагинов, которые позволяют автоматизировать рутинные операции и сделать процесс разработки эффективнее. Сегодня в нашей подборке 4 плагина

1. com.liferay.portal.tools.bundle.support

Представляет собой плагин для инфраструктуры, управления окружением и CI/CD. Реализует парадигму «Инфраструктура как код», позволяя избавиться от ручного скачивания архивов портала, распаковки и самостоятельного копирования конфигураций. Этот плагин берет под свой контроль весь жизненный цикл Liferay бандла. На основе указанного URL или версии плагин скачивает сборку сервера (например, Tomcat bundle) и кэширует архив в локальной файловой системе сборщика. Также плагин полностью очищает целевую директорию и разворачивает чистый инстанс Liferay, убирая все временные файлы, которые могут помешать деплою, исключая тем самым появление мусорных артефактов и кэша от старых запусков. Плагин также может накладывать файлы настроек (такие как portal-ext.properties или system-ext.properties) поверх чистого лайфрея в зависимости от выбранного профиля сборки (например, local, dev, test). Конфигурация разбивается на шаги (executions) в рамках конкретных фаз жизненного цикла (покажем пример для maven):

<project xmlns="http://apache.org" 
         xmlns:xsi="http://w3.org"
         xsi:schemaLocation="http://apache.org http://apache.org">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example.liferay</groupId>
    <artifactId>liferay-workspace-project</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <liferay.portal.tools.bundle.support.version>3.7.10</liferay.portal.tools.bundle.support.version>
        <liferay.bundle.dir>${project.basedir}/bundles</liferay.bundle.dir>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>com.liferay</groupId>
                <artifactId>com.liferay.portal.tools.bundle.support</artifactId>
                <version>${liferay.portal.tools.bundle.support.version}</version>
                
                <executions>
                    <!-- Полная очистка перед сборкой новой среды -->
                    <execution>
                        <id>clean-local-bundle</id>
                        <!-- Привязываем к стандартной фазе clean -->
                        <phase>clean</phase>
                        <goals>
                            <goal>clean-bundle</goal>
                        </goals>
                    </execution>

                    <!-- Скачивание и разворачивание чистого Liferay Bundle -->
                    <execution>
                        <id>initialize-liferay-server</id>
                        <!-- Привязываем к фазе инициализации проекта -->
                        <phase>initialize</phase>
                        <goals>
                            <goal>init-bundle</goal>
                        </goals>
                        <configuration>
                            <!-- URL для загрузки дистрибутива -->
                            <bundleURL>your URL</bundleURL>
                            <!-- Куда распаковывать -->
                            <destDir>${project.basedir}</destDir>
                        </configuration>
                    </execution>

                    <!-- Деплой  -->
                    <execution>
                        <id>deploy-global-configs</id>
                        <!-- Выполняется на этапе валидации или перед деплоем модулей -->
                        <phase>validate</phase>
                        <goals>
                            <goal>deploy</goal>
                        </goals>
                        <configuration>
                            <bundleDir>${liferay.bundle.dir}</bundleDir>
                            <!-- Копируем кастомные конфиги -->
                            <configsDir>${project.basedir}/configs/local</configsDir>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Кроме того, возможно использование локального бандла (уже собранного), что особенно актуально при использовании Wildfly:

 <configuration>
        <appServerType>wildfly</appServerType>
        <appServerBundleDir>${project.basedir}/bundles/wildfly</appServerBundleDir>
        <!-- директория Liferay Home для этого бандла -->
        <liferayHome>${project.basedir}/bundles</liferayHome>
 </configuration>

2. com.liferay.portal.tools.service.builder

Представляет собой плагин для генерации слоя доступа к данным (Java-классы, интерфейсы, SQL-скрипты, Hibernate/Spring-конфигурации) на основе одного XML-файла описания. Создает интерфейсы и базовые реализации для сервисов, генерирует DDL, обновляет базу и многое другое:

<plugin>
    <groupId>com.liferay</groupId>
    <artifactId>com.liferay.portal.tools.service.builder</artifactId>
    <version>1.0.420</version>
    <executions>
        <execution>
            <id>generate-service</id>
            <!-- Привязываем генерацию к фазе generate-sources, до компиляции Java -->
            <phase>generate-sources</phase>
            <goals>
                <goal>build-service</goal>
            </goals>
            <configuration>
                <!-- Главный файл с описанием сущностей и базы данных -->
                <inputFile>${project.basedir}/src/main/resources/META-INF/service.xml</inputFile>
                
                <!-- Куда сгенерируются интерфейсы и DTO -->
                <apiDir>${project.parent.basedir}/my-app-api/src/main/java</apiDir>
                
                <!-- Куда сгенерируется бизнес-логика и реализация -->
                <implDir>${project.basedir}/src/main/java</implDir>
                
                <!-- Папка для генерации SQL-скриптов создания таблиц и индексов -->
                <sqlDir>${project.basedir}/src/main/resources/META-INF/sql</sqlDir>
                
                <!-- Включать ли генерацию REST/JSON веб-сервисов -->
                <buildRemoteService>true</buildRemoteService>
               
                <!-- Включать ли генерацию локальных Java-сервисов -->
                <buildLocalService>true</buildLocalService>

            </configuration>
        </execution>
    </executions>
</plugin>

Чтобы плагин сработал, ему нужен файл конфигурации, где разработчик декларативно описывает сущности базы данных и их связи. Плагин же создает сотни строк сопутствующего кода. Вот минимальный пример файла src/main/resources/META-INF/service.xml для таблицы БД:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 7.4.0//EN" "http://liferay.com">

<service-builder dependency-injector="ds" package-path="com.example.myapp">
    <namespace>MYAPP</namespace>
    
        <!-- Первичный ключ -->
        <column name="bookId" type="long" primary="true" />
        
        <!-- Поля таблицы -->
        <column name="title" type="String" />
        <column name="author" type="String" />
        <column name="createDate" type="Date" />
        
        <!-- Индекс для быстрого поиска по автору -->
        <finder name="Author" return-type="Collection">
            <finder-column name="author" />
        </finder>
    
</service-builder>

3. com.liferay.portal.tools.rest.builder

Представляет собой плагин для генерации API (эндпоинты, схемы запросов/ответов). Разработчик описывает контракт своего API в стандартном формате OpenAPI (YAML), а плагин автоматически генерирует JAX-RS эндпоинты, DTO-модели, валидацию и Jackson-маппинг. Разработчику остаётся только написать бизнес-логику в классах реализации. Кроме того, плагин автоматически разворачивает эндпоинты в интерфейсе Swagger UI портала, делая API доступным для тестирования фронтенд-разработчиками сразу после деплоя бандла. Подключается так:

<plugin>
    <groupId>com.liferay</groupId>
    <artifactId>com.liferay.portal.tools.rest.builder</artifactId>
    <version>1.0.475</version>
    <executions>
        <execution>
            <id>generate-headless-api</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>build</goal>
            </goals>
            <configuration>
                <!-- Базовая папка, где лежат YAML схемы (rest-config.yaml, rest-openapi.yaml) -->
                <baseDir>${project.basedir}</baseDir>
                
                <!-- Относительный путь к подмодулю API, куда попадут сгенерированные интерфейсы -->
                <apiDir>../my-headless-api/src/main/java</apiDir>
                
                <!-- Путь в текущем модуле, куда попадет реализация REST -->
                <implDir>src/main/java</implDir>
            </configuration>
        </execution>
    </executions>
</plugin>

Для генерации API требуются два файла в модуле:

  • rest-openapi.yaml -- стандартное описание путей, методов (GET/POST/PUT) и моделей данных по спецификации OpenAPI 3.0.
openapi: 3.0.0
info:
  title: "My Custom API"
  version: v1.0
paths:
  /todos:
    get:
      operationId: getTodosPage
      description: "Получить список задач"
      responses:
        200:
          description: "Успешный ответ"
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Todo"
components:
  schemas:
    Todo:
      type: object
      properties:
        id:
          type: integer
          format: int64
        title:
          type: string
        completed:
          type: boolean
  • rest-config.yaml -- служебный файл Liferay, задает метаданные плагина, включая базовые пакеты, автора и системный контекст для OSGi:
apiPackagePath: "com.example.headless.api"
author: "Liferay Developer"
clientDir: "../my-headless-client/src/main/java" # если нужен клиент
compatibilityVersion: "7.4.0"
implPackagePath: "com.example.headless.internal"
jaxRsApplicationBaseUri: "/my-custom-api"
jaxRsApplicationName: "MyCustomAPI"

4. com.liferay.css.builder

Представляет собой плагин, который компилирует файлы стилей Sass (.scss) в стандартный CSS. В экосистеме Liferay этот плагин критически важен при сборке кастомных тем оформления, а также при стилизации отдельных портлетов и UI-компонентов. Он автоматически подтягивает глобальные стили ядра Liferay, обрабатывает импорты, миксины, переменные и минифицирует итоговый код. То есть CSS Builder предстает как Java-обертка над компилятором Sass, полностью интегрированная в сборочные контейнеры Gradle и Maven. Подключение на примере Maven:

<plugin>
    <groupId>com.liferay</groupId>
    <artifactId>com.liferay.css.builder</artifactId>
    <version>3.1.2</version>
    <executions>
        <execution>
            <id>compile-sass-to-css</id>
            <!-- Привязываем компиляцию стилей к фазе генерации ресурсов -->
            <phase>generate-resources</phase>
            <goals>
                <goal>build</goal>
            </goals>
            <configuration>
                <!-- Директория, где лежат исходные файлы .scss -->
                <docRootDir>${project.basedir}/src/main/resources/META-INF/resources</docRootDir>
                
                <!-- Подкаталог внутри docRootDir, где непосредственно искать .scss файлы -->
                <inputDir>/</inputDir>
                
                <!-- Куда складывать скомпилированные .css файлы -->
                <outputDir>/</outputDir>
                
                <!-- Включать ли генерацию Source Maps для удобной отладки в браузере -->
                <generateSourceMap>true</generateSourceMap>
                
                <!-- Стили, которые нужно исключить из прямой компиляции  -->
                <compilerExcludes>**/_*.scss</compilerExcludes>
                
                <!-- Пути к сторонним Sass-библиотекам или темам -->
                <importPaths>
                    <importPath>${project.basedir}/src/main/resources/META-INF/resources/node_modules</importPath>
                </importPaths>
            </configuration>
        </execution>
    </executions>
</plugin>

Итог

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

Next