Правильный способ использования Spring JAXB Marshaller с Java 9 без определения дополнительных модулей - PullRequest
0 голосов
/ 02 мая 2018

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

@SpringBootApplication
public class App implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

    @Bean
    public Jaxb2Marshaller jaxb2Marshaller() {
        Jaxb2Marshaller bean = new Jaxb2Marshaller();
        bean.setContextPath("ch.sahits.game.helloworld");
        return bean;
    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println("Started up");
    }
}

Этот код не запускается за исключением:

Caused by: java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
    at javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:122)
    at javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:155)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:174)
    ... 23 more

Что я не понимаю в этом исключении, так это то, почему com.sun.xml.internal.bind.v2.ContextFactory пытаются создать экземпляр? Было предложено , что мне также нужна зависимость для среды выполнения, поэтому я добавил:

<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.0</version>
</dependency>

Но это вызвало у меня другое исключение, когда я попытался загрузить другой класс:

Caused by: java.lang.ClassNotFoundException: com.sun.xml.bind.v2.model.annotation.AnnotationReader
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
    ... 39 more

Вот полный 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>ch.sahits.game</groupId>
    <artifactId>AddModuleDependencies</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <properties>
        <cxf-xjc-plugin.version>2.3.0</cxf-xjc-plugin.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>5.0.4.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.0</version>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>9</source>
                    <target>9</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-xjc-plugin</artifactId>
                <version>${cxf-xjc-plugin.version}</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>xsdtojava</goal>
                        </goals>
                        <configuration>
                            <extensions>
                                <extension>org.apache.cxf.xjcplugins:cxf-xjc-dv:${cxf-xjc-plugin.version}</extension>
                            </extensions>
                            <xsdOptions>
                                <xsdOption>
                                    <xsd>src/main/resources/helloworld.xsd</xsd>
                                    <bindingFile>src/main/resources/jaxb-binding.xjb</bindingFile>
                                    <packagename>ch.sahits.game.helloworld</packagename>
                                </xsdOption>
                            </xsdOptions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Самым простым решением, конечно, является добавление --add-modules java.xml.ws в качестве опции виртуальной машины, но это именно то, от чего я пытаюсь избавиться, чтобы сделать мое приложение перспективным. Какую зависимость я должен использовать, чтобы решить эту проблему? Или мне нужно изменить конфигурацию компонента, чтобы искать нужные классы (а не классы из com.sun.xml...)?

MCVE для скачать в виде zip-архива.

Ответы [ 2 ]

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

Следующее сработало для меня

<dependency>
  <groupId>org.glassfish.jaxb</groupId>
  <artifactId>jaxb-runtime</artifactId>
  <version>2.3.0</version>
</dependency>
0 голосов
/ 05 мая 2018

Попробуйте добавить следующее:

<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>com.sun.activation</groupId>
    <artifactId>javax.activation</artifactId>
    <version>1.2.0</version>
</dependency>

jaxb-core содержит com.sun.xml.bind.v2.model.annotation.AnnotationReader (и, по-видимому, является обязательной зависимостью jaxb-runtime, по крайней мере, в вашем случае), в то время как javax.activation требуется jaxb-api из-за использования DataHandler для последний.

Кроме того, нет единственного класса bean-компонента, поэтому маршаллеру не удастся выполнить инициализацию. Я добавил следующее

@XmlRootElement
public class MyBean {
}

и заменено

bean.setContextPath("ch.sahits.game.helloworld");

с

bean.setClassesToBeBound(MyBean.class);

после чего приложение запустилось.

...