在使用一些開源框架的時候(比如spark、hadoop、lucene等),偶爾會見到說找不到某個具體實現類或者某個配置(比如spark的akka配置)不見了。
部分例子如下:
【Lucene】An SPI class of type org.apache.lucene.codecs.PostingsFormat with name 'Lucene50' does not exist. You need to add the corresponding JAR file supporting this SPI to your classpath. The current classpath supports the following names: [es090, completion090, XBloomFilter]
小部分情況下,可能確實是配置問題或依賴問題沒解決好,所以第一步是檢查依賴或配置,比如上面的mapreduce錯誤,首先檢查yarn-site.xml的相應framework配置是不是為yarn。如果配置或依賴確認已經打包進去了,那么本質上其實是打包時同名文件被覆蓋的原因,尤其是maven assembly/shade常會遇見此類問題。
現象:其實配置是對的存在的,但是被覆蓋了;其實spi類是指定了的,但是manifest被覆蓋了。
解決辦法:先從報錯的源碼或配置等去定位,查看打包后jar里實際的配置或manifest是什么,根據實際情況使用shade插件打包並添加transform。
一個我常用的shade插件的示例
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.4.3</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>reference.conf</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <shadedArtifactAttached>true</shadedArtifactAttached> <shadedClassifierName>jar-with-dependencies</shadedClassifierName> </configuration> </execution> </executions> </plugin>
其中Appending那里的reference.conf是專門解決spark reference.conf文件同名導致akka配置被覆蓋的,另外兩個Manifest和Service是解決es、lucene的manifest配置備覆蓋的。其實這一類transform的解決文件沖突思路是把多個同名的根據一定規則拼成一個,比如manifest文件只拼接內容、Appending則是直接追加等。