MessageBodyProviderNotFoundException while running jar from command line

后端 未结 1 554
猫巷女王i
猫巷女王i 2020-11-27 22:38

I am using the Java Jersey framework(with Maven), and use IntelliJ as my IDE. I have encountered this runtime exception that ONLY happens when I try to run the code from the

相关标签:
1条回答
  • 2020-11-27 23:03

    If you look inside the jersey-media-json-jackson jar you should see a file

    META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
    

    The contents of this file should be a single fully qualified name of a class that implements the name of the file, namely

    org.glassfish.jersey.jackson.internal.JacksonAutoDiscoverable
    

    This file is used by Jersey auto-discoverable mechanism to automatically register features without us having to explicitly register them. Briefly, how it works, is that all Jersey modules/jars that have components that should be automatically registered, should have the above named file located in the jar, with the contents being the name(s) of the auto-discoverable component. Jersey will then use the Service Loader pattern to load the classes named in the file, and register them.

    The problem this causes when creating uber jars is that you can only have one copy of a file, you can't have duplicates. So what if we have multiple jars with the above file? Well only one of those files will be included in the uber jar. Which one? Who knows, but there is only one lucky winner. So for the rest of the jars, their auto-discover mechanism never kicks in. This is the case with your Jackson feature, where the auto-discoverable registers the JacksonFeature. You can try to explicitly register with your application, and you should see that it now works.

    But what about other jars/modules that may have this file? It's for this reason that when creating uber jars, you should use the maven-shade-plugin. What this plugin allows you to do, is combine the contents of the files so that all the discoverables get included into that one single file. Below is an example usage

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.3</version>
        <configuration>
            <createDependencyReducedPom>true</createDependencyReducedPom>
            <filters>
                <filter>
                    <artifact>*:*</artifact>
                    <excludes>
                        <exclude>META-INF/*.SF</exclude>
                        <exclude>META-INF/*.DSA</exclude>
                        <exclude>META-INF/*.RSA</exclude>
                    </excludes>
                </filter>
            </filters>
        </configuration>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <transformers>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <mainClass>com.example.YourApp</mainClass>
                        </transformer>
                    </transformers>
                </configuration>
            </execution>
        </executions>
    </plugin>
    

    This example was actually taken from Dropwizard's Getting Started. You can check it out for further explanation. The main part of concern the ServicesResorceTransformer, which is what concatenates the services files.

    0 讨论(0)
提交回复
热议问题