Генерация hashCode() и equals() при создании классов Java с использованием плагина Mojo Jaxb2 maven

Код, над которым я работаю, использует jaxb2-maven-plugin от org.codehaus.mojo генерировать классы Java из схемы XSD. Я ищу способ автоматически реализовать equals() а также hashCode() методы для этих классов, но, кажется, нет пути. Я знаю, что есть другие плагины JAXB2 Maven, которые делают это (http://confluence.highsource.org/display/J2B/Home, например), но мне было интересно, сталкивался ли кто-нибудь из вас с этой проблемой раньше и есть ли способ для исправить это. Я генерирую классы, используя xjc Цель.

6 ответов

Решение

Основы JAXB2, о которых вы упоминаете, не являются собственностью maven-jaxb2-pluginэто автономный набор плагинов JAXB 2.x, которые вы можете использовать с XJC - или jaxb2-maven-plugin или что угодно.

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxb2-maven-plugin</artifactId>
            <version>1.3.1</version>
            <executions>
                <execution>
                    <id>xjc</id>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                </execution>
           </executions>
           <configuration>
                <arguments>
                     <argument>-Xequals</argument>
                     <argument>-XhashCode</argument>
                </arguments>
           </configuration>
           <dependencies>
                <dependency>
                    <groupId>org.jvnet.jaxb2_commons</groupId>
                    <artifactId>jaxb2-basics</artifactId>
                    <version>0.11.1</version>
                </dependency>
           </dependencies>
       </plugin>

Что я хотел спросить - почему бы просто не использовать maven-jaxb2-plugin? Он обладает гораздо большей функциональностью по сравнению с плагином Codehaus, включая поддержку конфигурации для плагинов JAXB2.

Это самый простой способ сделать. Пожалуйста, обновите версию в соответствии с вашими требованиями.

<plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>jaxb2-maven-plugin</artifactId>
                    <version>1.5</version>
                    <dependencies>
                        <dependency>
                            <groupId>org.jvnet.jaxb2_commons</groupId>
                            <artifactId>jaxb2-commons-lang</artifactId>
                            <version>2.3</version>
                        </dependency>
                    </dependencies>
                    <executions>
                        <execution>
                            <id>JAXB generate content classes</id>
                            <phase>generate-sources</phase>
                            <goals>
                                <goal>xjc</goal>
                            </goals>
                            <configuration>
                                <schemaDirectory>${project.basedir}/src/main/resources/schema</schemaDirectory>
                                <outputDirectory>${project.build.directory}/generated-sources/jaxb</outputDirectory>
                                <schemaFiles>**/*.xsd</schemaFiles>
                                <packageName>com.lexus.web.content.model</packageName>
                                <arguments>-Xcommons-lang</arguments>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>

Я бы категорически не согласился с использованием сгенерированных JAXB классов в качестве бизнес-объектов в вашем коде. Классы, сгенерированные JAXB, являются компонентами, которые просто предназначены для того, чтобы по существу перемещать информацию об элементах из файла XML в поля компонента. Лично у меня всегда есть мой сервис SOAP, преобразующий эти сгенерированные классы bean-компонентов в мои настоящие бизнес-объекты, так как XML->Java и наоборот не всегда черно-белые. Обратите внимание, что это мое личное мнение, и я хотел бы, чтобы некоторые другие оценивали, что они делают в этой ситуации.

Чтобы ответить на ваш вопрос, используйте другой плагин или просто используйте IDE для создания методов equals и hashCode.

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ:

Я забыл привести свои аргументы в пользу этого, извинения. Допустим, в следующей версии вашего проекта вы хотите добавить больше поведения к сгенерированным JAXB классам, но также хотите внести некоторые изменения в свою схему. Теперь вы восстанавливаете сгенерированные JAXB классы, возвращаете старое поведение и, по моему мнению, делаете ваше приложение более восприимчивым к ошибкам. Предполагается, что сгенерированные JAXB классы отражают ваши типы схем XML (и, следовательно, ваши сообщения SOAP), а не вашу бизнес-логику. Надеюсь, что это имеет смысл.

Вы также можете рассмотреть возможность использования интерфейса Fluent Builder (облегчает обработку сгенерированных классов JAXB) и ссылки на файл каталога в случае, если вы ссылаетесь на схему xmldsig-core-схемы (ускоряет процесс генерации, так как нет удаленных схем от W3C запрашиваются - их серверы обычно задерживают ответ).

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxb2-maven-plugin</artifactId>
            <version>1.5</version>
            <dependencies>
                <dependency>
                    <groupId>net.java.dev.jaxb2-commons</groupId>
                    <artifactId>jaxb-fluent-api</artifactId>
                    <version>2.0.1</version>
                    <exclusions>
                        <exclusion>
                            <groupId>com.sun.xml</groupId>
                            <artifactId>jaxb-xjc</artifactId>
                        </exclusion>
                    </exclusions>
                </dependency>
                <dependency>
                    <groupId>org.jvnet.jaxb2_commons</groupId>
                    <artifactId>jaxb2-basics</artifactId>
                    <version>0.6.4</version>
                    <exclusions>
                        <exclusion>
                            <groupId>com.sun.xml</groupId>
                            <artifactId>jaxb-xjc</artifactId>
                        </exclusion>
                    </exclusions>
                </dependency>
            </dependencies>
            <executions>
                <execution>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <schemaDirectory>${basedir}/src/main/resources/xsd</schemaDirectory>
                <packageName>[your package name goes here]</packageName>
                <outputDirectory>${build.directory}/generated/src/main/java</outputDirectory>
                <bindingDirectory>${basedir}/src/main/resources/xsd</bindingDirectory>
                <extension>true</extension>
                <catalog>${basedir}/src/main/resources/xsd-catalog/catalog.cat</catalog>
                <extension>true</extension>
                <arguments>-Xfluent-api -Xequals -XhashCode -XtoString</arguments>
            </configuration>
        </plugin>

Вот как выглядит файл каталога:

--
  sample catalog file.

  double hyphens are used to begin and end a comment section.
--

SYSTEM "http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd" "xmldsig-core-schema.xsd"

А вот ссылка на xmldisg-core-schema.xsd: http://www.w3.org/TR/xmldsig-core/xmldsig-core-schema.xsd

Обратите внимание, что ссылка не битая - сервер W3C просто задерживает ответ на несколько секунд. Могу ли я быть очень громоздким, если это произойдет во время вашего автоматизированного процесса сборки, который включает генерацию JAXB.

Для меня самый простой способ сделать это с помощью maven-jaxb2-plugin (как указано в принятом ответе):

  1. Добавить в pom.xml <dependencies>
<dependency> 
    <groupId>org.jvnet.jaxb2_commons</groupId>
    <artifactId>jaxb2-basics</artifactId>
    <version>0.11.1</version>
</dependency>
  1. Добавьте плагин
<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.14.0</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <schemaDirectory>src/main/resources</schemaDirectory>
                <generateDirectory>target/generated-sources</generateDirectory>
                <generatePackage>my.package</generatePackage>
            </configuration>
        </execution>
    </executions>
    <configuration>
        <extension>true</extension>
        <args>
            <arg>-XtoString</arg>
            <arg>-Xequals</arg>
            <arg>-XhashCode</arg>
        </args>
        <plugins>
            <plugin>
                <groupId>org.jvnet.jaxb2_commons</groupId>
                <artifactId>jaxb2-basics</artifactId>
                <version>0.11.1</version>
            </plugin>
        </plugins>
    </configuration>
</plugin>

Видеть

Для JAXB также существует плагин fluent-builder, который не обязательно генерирует зависимости от стороннего кода. Кроме того, это настоящий шаблон проектирования "Builder", в то время как плагин "fluent-api" просто добавляет методы, схожие с построителями, к сгенерированным классам. Это: https://github.com/mklemm/jaxb2-rich-contract-plugin Он также имеет опции, позволяющие сделать сгенерированные классы неизменяемыми, и может генерировать методы для копирования состояния существующих объектов в новый экземпляр компоновщика, также поддерживая "частичная" копия объекта.

Мой ответ - для тех, кто не может позволить себе какую-либо зависимость третьей стороны от их сгенерированного кода.

Плагин org.jvnet.jaxb2_commons:jaxb2-basics добавляет множество org.jvnet включает в сгенерированный код и ваш проект будет зависеть от org.jvnet.jaxb2_commons:jaxb2-basics-runtime,

http://mvnrepository.com/artifact/org.andromda.thirdparty.jaxb2_commons/commons-lang-plugin plugin генерирует код, который зависит от commons-lang:commons-lang, Эта зависимость может быть легче вынести в зависимости от ситуации.

Наконец-то я нашел этот исходный код, он может быть в какой- то момент включен в com.sun.xml.bind:jaxb-xjc (версия 2.2.4?), Но до тех пор я не вижу другого решения, кроме написания собственного плагина,

PS: я не могу получить доступ к http://confluence.highsource.org/display/J2B/Equals+plugin, я получаю 404. Я думаю, это могло бы быть полезно.

PPS: В моей ситуации приложение, которое я создаю, предназначено для среды, которая имеет очень ограниченный набор разрешенных библиотек Java (несоответствующие ограничения безопасности). Я был немного разочарован тем фактом, что jaxb2_commons включает в себя кучу org.jvnet зависимости в сгенерированном источнике, просто для добавления скучно equals метод. Я могу понять стратегию jvnet, их инструменты очень мощные, возможно, я просто пытаюсь использовать кувалду, чтобы сломать орех. Тем не менее, мне было жаль отмечать, что было очень трудно найти подходящий инструмент для моей ситуации.

Другие вопросы по тегам