maven-jaxb2-plugin, повторно использующий XSD в общем проекте - PullRequest
0 голосов
/ 04 мая 2018

У меня есть проект, который имеет схему A и B, оба в одном и том же пространстве имен. Оба импортируют схему C, которая также использует одно и то же пространство имен. Как я могу сгенерировать классы JAXB для A и B для разделения пакетов, при этом повторно используя классы JAXB из C, сгенерированного в пакет commons?

Я уже знаю, что, вероятно, мне следует использовать эпизоды и использовать эпизод, сгенерированный для схемы C, в качестве файла привязок для отдельных исполнений схем A и B. Проблема в том, что я не знаю, как ссылаться на этот сгенерированный файл эпизодов.

Вот пример:

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.12.3</version>
    <executions>
        <execution>
            <id>generate-sources-C</id>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <generatePackage>com.mymodel.commons</generatePackage>
                <generateDirectory>${project.build.directory}/generated-sources/xjc-commons</generateDirectory>
                <schemas>
                    <schema><url>src/main/resources/xsd/mymodel/c.xsd</url></schema>
                </schemas>
            </configuration>
        </execution>
        <execution>
            <id>generate-sources-A</id>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <generatePackage>com.mymodel.a</generatePackage>
                <schemas>
                    <schema><url>src/main/resources/xsd/mymodel/a.xsd</url></schema>
                </schemas>
            </configuration>
        </execution>
        <execution>
            <id>generate-sources-B</id>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <generatePackage>com.mymodel.b</generatePackage>
                <schemas>
                    <schema><url>src/main/resources/xsd/mymodel/b.xsd</url></schema>
                </schemas>
            </configuration>
        </execution>
    </executions>
</plugin>

Это вызывает создание файла эпизода в:

target/generated-sources/xjc-commons/META-INF/sun-jaxb.episode

Как мне обратиться к этому файлу эпизодов / привязок в исполнениях для A и B? Использование эпизодов только упоминает, как обращаться к файлу эпизода из других зависимостей jar (или я просто не понял его правильно, что более вероятно).

Я видел более старый ответ, предлагающий передать его в качестве параметра -b в XJC, но это, похоже, ничего не сделало для меня. Я до сих пор получаю тот же класс из C, сгенерированный три раза.

1 Ответ

0 голосов
/ 04 мая 2018

Отказ от ответственности: Я являюсь автором .

TL; DR вот тестовый проект , который демонстрирует, как это сделать.

Это возможно, но немного волосато, поэтому, пожалуйста, потерпите меня.

Если a.xsd, b.xsd и c.xsd находятся в одном и том же пространстве имен, a.xsd и b.xsd не могут импортировать c.xsd, они могут только включать Это. Мы хотим сгенерировать каждый из XSD в свой собственный пакет, скажем, test.a, test.b и test.c и сделать это в одном и том же проекте Maven.

Для этого нам понадобятся три отдельных исполнения maven-jaxb2-plugin, каждое из которых настроено на собственную схему и целевой пакет. Например:

        <plugin>
            <groupId>org.jvnet.jaxb2.maven2</groupId>
            <artifactId>maven-jaxb2-plugin</artifactId>
            <executions>
                <execution>
                    <id>xjc-a</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                    <configuration>
                        <generatePackage>test.a</generatePackage>
                        <generateDirectory>${project.build.directory}/xjc-a</generateDirectory>
                        <schemaIncludes>
                            <includes>a.xsd</includes>
                        </schemaIncludes>
                    </configuration>
                </execution>
                <!-- xjc-b and xjc-c follow -->
            </executions>
        </plugin>

Важно использовать разные целевые каталоги для отдельных исполнений .

ОК, это создаст три целевых каталога с тремя целевыми пакетами. Следующая проблема заключается в том, что классы из c.xsd будут сгенерированы в test.a и test.b, которых мы хотим избежать.

Чтобы добиться этого, мы должны указать XJC использовать классы из test.c для типов из c.xsd. Это на самом деле то, для чего эпизод файл. Этот файл обычно создается в META-INF\sun-jaxb.episode и содержит привязки для всех типов в обработанной схеме. Вот пример, сгенерированный для c.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" if-exists="true" version="2.1">
  <bindings xmlns:tns="urn:test" if-exists="true" scd="x-schema::tns">
    <schemaBindings map="false">
      <package name="test.c"/>
    </schemaBindings>
    <bindings if-exists="true" scd="~tns:CType">
      <class ref="test.c.CType"/>
    </bindings>
  </bindings>
</bindings>

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

                <execution>
                    <id>xjc-a</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                    <configuration>
                        <generatePackage>test.a</generatePackage>
                        <generateDirectory>${project.build.directory}/xjc-a</generateDirectory>
                        <schemaIncludes>
                            <includes>a.xsd</includes>
                        </schemaIncludes>
                        <bindings>
                            <binding>
                                <fileset>
                                    <directory>${project.build.directory}/xjc-c/META-INF</directory>
                                    <includes>
                                        <include>sun-jaxb.episode</include>
                                    </includes>
                                </fileset>
                            </binding>
                        </bindings>
                    </configuration>
                </execution>

Осталась только одна крошечная проблема. Файлы эпизодов, сгенерированные XJC, также содержат этот фрагмент:

    <schemaBindings map="false">
      <!-- ... -->
    </schemaBindings>

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

.

Чтобы обойти это, мы можем постобработать sun-jaxb.episode, который был сгенерирован для c.xsd. Это можно сделать с помощью простого XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="1.0">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="jaxb:schemaBindings"/>
</xsl:stylesheet>

Этот XSLT следует запускать после кода для c.xsd, но до генерации кода для a.xsd и b.xsd. Этого можно достичь, поместив эти исполнения в разные фазы (generate-sources, process-sources, generate-resources).


Ниже приведено полное 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.jvnet.jaxb2.maven2</groupId>
    <artifactId>divide</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.2.11</version>
        </dependency>
        <!-- JUnit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
            <version>4.12</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>xml-maven-plugin</artifactId>
                <version>1.0.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>transform</goal>
                        </goals>
                        <phase>process-sources</phase>
                    </execution>
                </executions>
                <configuration>
                    <transformationSets>
                        <transformationSet>
                            <dir>${project.build.directory}/xjc-c/META-INF</dir>
                            <outputDir>${project.build.directory}/xjc-c/META-INF</outputDir>
                            <includes>
                                <include>sun-jaxb.episode</include>
                            </includes>
                            <stylesheet>src/main/xslt/removeJaxbSchemaBindings.xslt</stylesheet>
                        </transformationSet>
                    </transformationSets>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.jvnet.jaxb2.maven2</groupId>
                <artifactId>maven-jaxb2-plugin</artifactId>
                <version>0.13.3</version>
                <executions>
                    <execution>
                        <id>xjc-c</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <phase>generate-sources</phase>
                        <configuration>
                            <generatePackage>test.c</generatePackage>
                            <generateDirectory>${project.build.directory}/xjc-c</generateDirectory>
                            <schemaIncludes>
                                <includes>c.xsd</includes>
                            </schemaIncludes>
                        </configuration>
                    </execution>
                    <execution>
                        <id>xjc-a</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <phase>generate-resources</phase>
                        <configuration>
                            <generatePackage>test.a</generatePackage>
                            <generateDirectory>${project.build.directory}/xjc-a</generateDirectory>
                            <schemaIncludes>
                                <includes>a.xsd</includes>
                            </schemaIncludes>
                            <bindings>
                                <binding>
                                    <fileset>
                                        <directory>${project.build.directory}/xjc-c/META-INF</directory>
                                        <includes>
                                            <include>sun-jaxb.episode</include>
                                        </includes>
                                    </fileset>
                                </binding>
                            </bindings>
                        </configuration>
                    </execution>
                    <execution>
                        <id>xjc-b</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <phase>generate-resources</phase>
                        <configuration>
                            <generatePackage>test.b</generatePackage>
                            <generateDirectory>${project.build.directory}/xjc-b</generateDirectory>
                            <schemaIncludes>
                                <includes>b.xsd</includes>
                            </schemaIncludes>
                            <bindings>
                                <binding>
                                    <fileset>
                                        <directory>${project.build.directory}/xjc-c/META-INF</directory>
                                        <includes>
                                            <include>sun-jaxb.episode</include>
                                        </includes>
                                    </fileset>
                                </binding>
                            </bindings>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
...