Допустим отдел аналитики подготовил нам Swagger YAML с описанием API доступа к какому-то сервису: xyz-swagger-v1.0.0.yaml.
Как автоматизировать генерацию библиотеки для доступа к API по этому описанию, если у вас maven? Полного мануала почему-то нигде нет, так что я собрал в одну всю информацию о реализации и возможных проблемах.

Для генерации нам понадобятся следующие плагины для maven:

  • maven-clean-plugin — удаляет файлы. Он нужен, чтобы очистить директорию с исходниками проекта от предыдущей сгенерированной версии. Настройки, на которые следует обратить внимание:

    • configuration.filesets.fileset.directory: ${project.basedir}/src/main/java — мы будем очищать директорию самого приложения

    • configuration.filesets.fileset.includes.include: ** — не только очищать директорию /src/main/java, но и удалять её саму.

  • openapi-generator-maven-plugin — генерирует по OpenAPI YAML для Swagger Java-классы. Настройки, на которые следует обратить внимание:

    • apiPackage — пространства имён для классов сервисов API

    • modelPackage — пространства имён для классов моделей

    • output: ${project.basedir} — если настроить его так, сгенерированные файлы падали не в target, а прямо в папку с кодом

Сгенерированные файлы используют аннотации и методы из внешних библиотек. Поэтому в dependencies нужно будет добавить:

  • spring-boot-starter-web версии 2.4.4

  • spring-data-jpa версии версии 2.4.6

  • jackson-databind-nullable версии 0.2.6

  • springdoc-openapi-ui версии 1.8.0

Если какой-то из этих версий нет в доступных вашему проекту репозиториях — используйте те, которые доступны. Но увеличивайте версию осторожно и перепроверяйте после каждого изменения: как минимум spring-boot-starter-web и spring-data-jpa не совсем обратно совместимы и при повышении их версии в сгенерированных файлах может перестать распозновать зависимости.

Создайте пустой проект с поддержкой Maven и удалите весь код из папки java.

Поместите в папку /src/main/resources/ файл с YAML-описанием OpenAPI для Swagger. В моём примере это xyz-swagger-v1.0.0.yaml

В результате pom.xml будет выглядеть примерно как-то так:

<?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.mycompany</groupId>
    <artifactId>xyz-api-service</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
	    <maven.compiler.source>17</maven.compiler.source>
	    <maven.compiler.target>17</maven.compiler.target>
	    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	    <spring-boot-starter-web.version>2.4.4</spring-boot-starter-web.version>
	    <spring-data-jpa.version>2.4.6</spring-data-jpa.version>
	    <jackson-databind-nullable.version>0.2.6</jackson-databind-nullable.version>
        <springdoc-openapi-ui.version>1.8.0</springdoc-openapi-ui.version>
	    <openapi-generator-maven-plugin.version>7.1.0</openapi-generator-maven-plugin.version>
	    <maven-clean-plugin.version>2.4.1</maven-clean-plugin.version>
	    <swagger-yaml>xyz-swagger-v${swagger-yaml.version}.yaml</swagger-yaml>
	    <swagger-yaml.version>1.0.0</swagger-yaml.version>
    </properties>
    <dependencies>
		<dependency>
			    <groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-starter-web</artifactId>
				<version>${spring-boot-starter-web.version}</version>
			</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>${spring-data-jpa.version}</version>
        </dependency>
	    <dependency>
		    <groupId>org.openapitools</groupId>
		    <artifactId>jackson-databind-nullable</artifactId>
		    <version>${jackson-databind-nullable.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springdoc</groupId>
			<artifactId>springdoc-openapi-ui</artifactId>
			<version>${springdoc-openapi-ui.version}</version>
		</dependency>
	</dependencies>
    <build>
	    <plugins>
		    <plugin>
			    <artifactId>maven-clean-plugin</artifactId>
			    <version>${maven-clean-plugin.version}</version>
			    <configuration>
				    <filesets>
					    <fileset>
						    <directory>${project.basedir}/src/main/java</directory>
							<includes>
								<include>**</include>
							</includes>
							<followSymlinks>false</followSymlinks>
						</fileset>
					</filesets>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.openapitools</groupId>
				<artifactId>openapi-generator-maven-plugin</artifactId>
				<version>${openapi-generator-maven-plugin.version}</version>
				<executions>
					<execution>
						<goals>
							<goal>generate</goal>
						</goals>
					<configuration>
						<inputSpec>${project.basedir}/src/main/resources/${swagger-yaml}</inputSpec>
						<generatorName>spring</generatorName>
						<apiPackage>org.mycompany.xyz.api</apiPackage>
						<modelPackage>org.mycompany.xyz.model</modelPackage>
						<supportingFilesToGenerate>ApiUtil.java</supportingFilesToGenerate
						<configOptions>
							<delegatePattern>true</delegatePattern>
						</configOptions>
						<output>${project.basedir}</output>
					</configuration>
				</execution>
			</executions>
			</plugin>
	    </plugins>
    </build>
</project>

При обновлении версии файла будет достаточно заменить свойство swagger-yaml.version. А формат имени файла указывается в свойстве swagger-yaml.

Чтобы сгенерировать файлы, просто выполните из консоли или интерфейса вашей IDE две команды жизненного цикла Maven: clean и compile.

И сгенерированные файлы появятся прямо в рабочей директории. При новой генерации старые файлы будут удаляться автоматически

Важно: не пытайтесь запускать указанные плагины напрямую. Напрямую они просто не будут работать.

Небольшой штришок — чтобы не мусорить в репозитории, нужно добавить в .gitignore (для Git, в Mercurial этот файл называется .hgignore) пометку о том, что нужно игнорировать временные файлы, которые создаёт плагин:

.openapi-generator

Комментарии (1)


  1. Pr1st
    30.08.2024 05:33

    Указывать в clean плагине "configuration.filesets.fileset.directory: ${project.basedir}/src/main/java" это кончно сильно

    Для незнающих, хороший совет: не указывайте в плагинах генерирующие ресуры (например openapi-generator-maven-plugin) "src", нужно указывать специально для этого спроектированную "target/generated-sources" и clean плагин не надо будет кастомизировать.

    Подробнее есть например в ответе тут: https://stackoverflow.com/questions/21340508/how-can-i-organize-source-generation-in-maven