启动 Optaplanner 应用程序时异常子服务没有父服务
Exception Child services have no parent when starting Optaplanner application
我有一个使用 optaplanner 的测试程序。没有直接使用 KIE API,但看起来它们是在幕后调用的。这可能与我使用 DROOLS 计算分数有关。该程序从 IDE 或通过 maven 运行,但我想创建一个不需要 maven 的独立 jar。
我使用 Maven 程序集插件构建了一个包含所有依赖项的胖 jar 运行 独立。
当我 运行 java -jar target/OptaPlannerTest-1.4-SNAPSHOT-jar-with-dependencies.jar
我得到:
Exception in thread "main" java.lang.ExceptionInInitializerError
at org.kie.api.internal.utils.ServiceRegistry.getInstance(ServiceRegistry.java:27)
at org.kie.api.KieServices$Factory$LazyHolder.<clinit>(KieServices.java:332)
at org.kie.api.KieServices$Factory.get(KieServices.java:339)
at org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildDroolsScoreDirectorFactory(ScoreDirectorFactoryConfig.java:460)
at org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildScoreDirectorFactory(ScoreDirectorFactoryConfig.java:331)
at org.optaplanner.core.config.solver.SolverConfig.buildSolver(SolverConfig.java:220)
at org.optaplanner.core.impl.solver.AbstractSolverFactory.buildSolver(AbstractSolverFactory.java:61)
at com.github.wshackle.optaplannertest.Main.main(Main.java:38)
Caused by: java.lang.RuntimeException: Child services [org.kie.api.internal.assembler.KieAssemblers] have no parent
at org.kie.api.internal.utils.ServiceDiscoveryImpl.buildMap(ServiceDiscoveryImpl.java:186)
at org.kie.api.internal.utils.ServiceDiscoveryImpl.getServices(ServiceDiscoveryImpl.java:97)
at org.kie.api.internal.utils.ServiceRegistryImpl.<init>(ServiceRegistryImpl.java:36)
at org.kie.api.internal.utils.ServiceRegistryImpl$LazyHolder.<clinit>(ServiceRegistryImpl.java:32)
Main.java 的第 38 行只有两行进入应用程序,所以它所做的只是加载配置文件并尝试构建求解器。
SolverFactory<Plan> solverFactory = SolverFactory.createFromXmlResource(
"com/github/wshackle/optaplannertest/solverConfig.xml");
Solver<Plan> solver = solverFactory.buildSolver();
solverConfig.xml 是:
<solver>
<!-- Domain model configuration -->
<scanAnnotatedClasses>
<packageInclude>com.github.wshackle.optaplannertest.model</packageInclude>
</scanAnnotatedClasses>
<!-- Score configuration -->
<scoreDirectorFactory>
<scoreDrl>com/github/wshackle/optaplannertest/scoreRules.drl</scoreDrl>
</scoreDirectorFactory>
<!-- Optimization algorithms configuration -->
<termination>
<secondsSpentLimit>5</secondsSpentLimit>
</termination>
</solver>
在 cast 中它是相关的,我的 pom 是这样的:
<?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>com.github.wshackle</groupId>
<artifactId>OptaPlannerTest</artifactId>
<version>1.4-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<optiplanner.version>7.3.0.Final</optiplanner.version>
<main.class>com.github.wshackle.optaplannertest.Main</main.class>
</properties>
<dependencies>
<dependency>
<groupId>org.optaplanner</groupId>
<artifactId>optaplanner-core</artifactId>
<version>${optiplanner.version}</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>${optiplanner.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
<version>1.2.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<archive>
<manifest>
<mainClass>${main.class}</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
jar 中的完整文件列表显示在
https://gist.github.com/wshackle/8887aac8a10e8c4b1f862a4bda288e41
我使用 grep 来验证它们似乎包含每个 jar 依赖项的预期 类:
> grep -c org/kie/api jarlisting.txt
391
> grep -c org/kie/internal jarlisting.txt
364
> grep -c org/optaplanner/core jarlisting.txt
841
> grep -c org/drools/core jarlisting.txt
2175
> grep -c org/drools/compiler jarlisting.txt
832
运行 "mvn dependency:tree" 并且您会看到 optaplanner-core 依赖于 kie-api、kie-internal-api、drools-core 和 drools-编译器。其中一个将在您的脂肪罐中丢失。
我在使用以下 pom 时遇到了同样的问题
<?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>
..
<dependencies>
<dependency>
<groupId>org.optaplanner</groupId>
<artifactId>optaplanner-core</artifactId>
<version>${optaPlanner.version}</version>
</dependency>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${jar.plugin.version}</version>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
<compress>false</compress>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>${mainClass}</mainClass>
</manifest>
<index>true</index>
<manifestEntries>
<impl-version>${project.version}</impl-version>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${dependency.plugin.version}</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>${assembly.plugin.version}</version>
<configuration>
<descriptors>
<descriptor>assembly/release.xml</descriptor>
</descriptors>
<finalName>${distribution.file.name}</finalName>
<outputDirectory>${project.build.directory}/dist</outputDirectory>
<workDirectory>${project.build.directory}/assembly/work</workDirectory>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
删除
<index>true</index>
解决了我的问题。希望这对其他人也有帮助。
问题是以下jar文件都包含不同版本的META-INF/kie.conf
:
optaplanner-core-7.3.0.Final.jar
kie-internal/7.3.0.Final/kie-internal-7.3.0.Final.jar
drools-core-7.3.0.Final.jar
drools-compiler-7.3.0.Final.jar
当maven-assembly-plugin将它们放在一起时,只能包含META-INF/kie.conf
的一个版本。在构建求解器时,Optaplanner 库将在当前线程上下文类加载器上间接调用 getResources("META-INF/kie.conf")
。如果类路径上有多个 jar,那么它们都会被找到,生成的配置将是解析所有这些的产物。为了在单个 fat uber jar 中完成这项工作,需要将 kie.conf 文件移动到不同的文件名,并重载类加载器以指示库以新名称使用它们。 (也可以将它们组合成一个 kie.conf 文件)
提取并移动 kie.conf 个文件:
jar -xf ~/.m2/repository/org/optaplanner/optaplanner-core/7.3.0.Final/optaplanner-core-7.3.0.Final.jar META-INF/kie.conf
mv META-INF/kie.conf src/main/resources/optaplanner-core-kie.conf
jar -xf ~/.m2/repository/org/kie/kie-internal/7.3.0.Final/kie-internal-7.3.0.Final.jar META-INF/kie.conf
mv META-INF/kie.conf src/main/resources/kie-internal-kie.conf
jar -xf ~/.m2/repository/org/drools/drools-core/7.3.0.Final/drools-core-7.3.0.Final.jar META-INF/kie.conf
mv META-INF/kie.conf src/main/resources/drools-core-kie.conf
jar -xf ~/.m2/repository/org/drools/drools-compiler/7.3.0.Final/drools-compiler-7.3.0.Final.jar META-INF/kie.conf
mv META-INF/kie.conf src/main/resources/drools-compiler-kie.conf
然后重载并设置线程上下文加载器。
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
URL[] localKieConfUrls = new URL[]{
ClassLoader.getSystemResource("optaplanner-core-kie.conf"),
ClassLoader.getSystemResource("kie-internal-kie.conf"),
ClassLoader.getSystemResource("drools-core-kie.conf"),
ClassLoader.getSystemResource("drools-compiler-kie.conf")
};
ClassLoader newClassLoader = new ClassLoader(oldClassLoader) {
private final URL[] kieConfUrls = localKieConfUrls;
@Override
public Enumeration<URL> getResources(String name) throws IOException {
if ("META-INF/kie.conf".equals(name)) {
return new Enumeration<URL>() {
int index;
@Override
public boolean hasMoreElements() {
return index < kieConfUrls.length;
}
@Override
public URL nextElement() {
return kieConfUrls[index++];
}
};
}
return super.getResources(name);
}
};
Thread.currentThread().setContextClassLoader(newClassLoader);
对于使用 maven-shade-plugin 的人,这里有一个建议的修复程序,它将使用 AppendingTransformer [=11 将复制的 META-INF/kie.conf 合并到一个文件中=]
我同意问题如@WillSchackleford 所述:
The problem is that the following jar files all contain different versions of META-INF/kie.conf:
optaplanner-core-7.3.0.Final.jar
kie-internal/7.3.0.Final/kie-internal-7.3.0.Final.jar
drools-core-7.3.0.Final.jar
drools-compiler-7.3.0.Final.jar
When the maven-assembly-plugin puts them together only one version of the META-INF/kie.conf can be included.
合并所有这些 kie.conf 文件的最佳技巧是在您的 Maven 配置中使用 transformer
,如下所示:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<!-- get all project dependencies -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- MainClass in mainfest make a executable jar -->
<archive>
<manifest>
<mainClass>com.paconsulting.powerpeers.PowerPeersDemo</mainClass>
</manifest>
</archive>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/kie.conf</resource>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
这将创建一个 META-INF/kie.conf
文件,其中包含它找到的任何 kie.conf
文件的内容。
我也遇到过这个错误,但我找到了不同的解决方法。与生成具有所有依赖项的 jar 文件不同,生成具有依赖项库文件夹的 jar 文件是获取可运行 jar 文件的更简单方法。要使用 lib 文件夹生成 jar 文件,请如下所示修改您的 pom.xml 文件。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClassMain-Class</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
我有一个使用 optaplanner 的测试程序。没有直接使用 KIE API,但看起来它们是在幕后调用的。这可能与我使用 DROOLS 计算分数有关。该程序从 IDE 或通过 maven 运行,但我想创建一个不需要 maven 的独立 jar。 我使用 Maven 程序集插件构建了一个包含所有依赖项的胖 jar 运行 独立。
当我 运行 java -jar target/OptaPlannerTest-1.4-SNAPSHOT-jar-with-dependencies.jar
我得到:
Exception in thread "main" java.lang.ExceptionInInitializerError
at org.kie.api.internal.utils.ServiceRegistry.getInstance(ServiceRegistry.java:27)
at org.kie.api.KieServices$Factory$LazyHolder.<clinit>(KieServices.java:332)
at org.kie.api.KieServices$Factory.get(KieServices.java:339)
at org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildDroolsScoreDirectorFactory(ScoreDirectorFactoryConfig.java:460)
at org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildScoreDirectorFactory(ScoreDirectorFactoryConfig.java:331)
at org.optaplanner.core.config.solver.SolverConfig.buildSolver(SolverConfig.java:220)
at org.optaplanner.core.impl.solver.AbstractSolverFactory.buildSolver(AbstractSolverFactory.java:61)
at com.github.wshackle.optaplannertest.Main.main(Main.java:38)
Caused by: java.lang.RuntimeException: Child services [org.kie.api.internal.assembler.KieAssemblers] have no parent
at org.kie.api.internal.utils.ServiceDiscoveryImpl.buildMap(ServiceDiscoveryImpl.java:186)
at org.kie.api.internal.utils.ServiceDiscoveryImpl.getServices(ServiceDiscoveryImpl.java:97)
at org.kie.api.internal.utils.ServiceRegistryImpl.<init>(ServiceRegistryImpl.java:36)
at org.kie.api.internal.utils.ServiceRegistryImpl$LazyHolder.<clinit>(ServiceRegistryImpl.java:32)
Main.java 的第 38 行只有两行进入应用程序,所以它所做的只是加载配置文件并尝试构建求解器。
SolverFactory<Plan> solverFactory = SolverFactory.createFromXmlResource(
"com/github/wshackle/optaplannertest/solverConfig.xml");
Solver<Plan> solver = solverFactory.buildSolver();
solverConfig.xml 是:
<solver>
<!-- Domain model configuration -->
<scanAnnotatedClasses>
<packageInclude>com.github.wshackle.optaplannertest.model</packageInclude>
</scanAnnotatedClasses>
<!-- Score configuration -->
<scoreDirectorFactory>
<scoreDrl>com/github/wshackle/optaplannertest/scoreRules.drl</scoreDrl>
</scoreDirectorFactory>
<!-- Optimization algorithms configuration -->
<termination>
<secondsSpentLimit>5</secondsSpentLimit>
</termination>
</solver>
在 cast 中它是相关的,我的 pom 是这样的:
<?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>com.github.wshackle</groupId>
<artifactId>OptaPlannerTest</artifactId>
<version>1.4-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<optiplanner.version>7.3.0.Final</optiplanner.version>
<main.class>com.github.wshackle.optaplannertest.Main</main.class>
</properties>
<dependencies>
<dependency>
<groupId>org.optaplanner</groupId>
<artifactId>optaplanner-core</artifactId>
<version>${optiplanner.version}</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>${optiplanner.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
<version>1.2.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<archive>
<manifest>
<mainClass>${main.class}</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
jar 中的完整文件列表显示在 https://gist.github.com/wshackle/8887aac8a10e8c4b1f862a4bda288e41
我使用 grep 来验证它们似乎包含每个 jar 依赖项的预期 类:
> grep -c org/kie/api jarlisting.txt
391
> grep -c org/kie/internal jarlisting.txt
364
> grep -c org/optaplanner/core jarlisting.txt
841
> grep -c org/drools/core jarlisting.txt
2175
> grep -c org/drools/compiler jarlisting.txt
832
运行 "mvn dependency:tree" 并且您会看到 optaplanner-core 依赖于 kie-api、kie-internal-api、drools-core 和 drools-编译器。其中一个将在您的脂肪罐中丢失。
我在使用以下 pom 时遇到了同样的问题
<?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>
..
<dependencies>
<dependency>
<groupId>org.optaplanner</groupId>
<artifactId>optaplanner-core</artifactId>
<version>${optaPlanner.version}</version>
</dependency>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${jar.plugin.version}</version>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
<compress>false</compress>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>${mainClass}</mainClass>
</manifest>
<index>true</index>
<manifestEntries>
<impl-version>${project.version}</impl-version>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${dependency.plugin.version}</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>${assembly.plugin.version}</version>
<configuration>
<descriptors>
<descriptor>assembly/release.xml</descriptor>
</descriptors>
<finalName>${distribution.file.name}</finalName>
<outputDirectory>${project.build.directory}/dist</outputDirectory>
<workDirectory>${project.build.directory}/assembly/work</workDirectory>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
删除
<index>true</index>
解决了我的问题。希望这对其他人也有帮助。
问题是以下jar文件都包含不同版本的META-INF/kie.conf
:
optaplanner-core-7.3.0.Final.jar
kie-internal/7.3.0.Final/kie-internal-7.3.0.Final.jar
drools-core-7.3.0.Final.jar
drools-compiler-7.3.0.Final.jar
当maven-assembly-plugin将它们放在一起时,只能包含META-INF/kie.conf
的一个版本。在构建求解器时,Optaplanner 库将在当前线程上下文类加载器上间接调用 getResources("META-INF/kie.conf")
。如果类路径上有多个 jar,那么它们都会被找到,生成的配置将是解析所有这些的产物。为了在单个 fat uber jar 中完成这项工作,需要将 kie.conf 文件移动到不同的文件名,并重载类加载器以指示库以新名称使用它们。 (也可以将它们组合成一个 kie.conf 文件)
提取并移动 kie.conf 个文件:
jar -xf ~/.m2/repository/org/optaplanner/optaplanner-core/7.3.0.Final/optaplanner-core-7.3.0.Final.jar META-INF/kie.conf
mv META-INF/kie.conf src/main/resources/optaplanner-core-kie.conf
jar -xf ~/.m2/repository/org/kie/kie-internal/7.3.0.Final/kie-internal-7.3.0.Final.jar META-INF/kie.conf
mv META-INF/kie.conf src/main/resources/kie-internal-kie.conf
jar -xf ~/.m2/repository/org/drools/drools-core/7.3.0.Final/drools-core-7.3.0.Final.jar META-INF/kie.conf
mv META-INF/kie.conf src/main/resources/drools-core-kie.conf
jar -xf ~/.m2/repository/org/drools/drools-compiler/7.3.0.Final/drools-compiler-7.3.0.Final.jar META-INF/kie.conf
mv META-INF/kie.conf src/main/resources/drools-compiler-kie.conf
然后重载并设置线程上下文加载器。
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
URL[] localKieConfUrls = new URL[]{
ClassLoader.getSystemResource("optaplanner-core-kie.conf"),
ClassLoader.getSystemResource("kie-internal-kie.conf"),
ClassLoader.getSystemResource("drools-core-kie.conf"),
ClassLoader.getSystemResource("drools-compiler-kie.conf")
};
ClassLoader newClassLoader = new ClassLoader(oldClassLoader) {
private final URL[] kieConfUrls = localKieConfUrls;
@Override
public Enumeration<URL> getResources(String name) throws IOException {
if ("META-INF/kie.conf".equals(name)) {
return new Enumeration<URL>() {
int index;
@Override
public boolean hasMoreElements() {
return index < kieConfUrls.length;
}
@Override
public URL nextElement() {
return kieConfUrls[index++];
}
};
}
return super.getResources(name);
}
};
Thread.currentThread().setContextClassLoader(newClassLoader);
对于使用 maven-shade-plugin 的人,这里有一个建议的修复程序,它将使用 AppendingTransformer [=11 将复制的 META-INF/kie.conf 合并到一个文件中=]
我同意问题如@WillSchackleford 所述:
The problem is that the following jar files all contain different versions of META-INF/kie.conf:
optaplanner-core-7.3.0.Final.jar kie-internal/7.3.0.Final/kie-internal-7.3.0.Final.jar drools-core-7.3.0.Final.jar drools-compiler-7.3.0.Final.jar
When the maven-assembly-plugin puts them together only one version of the META-INF/kie.conf can be included.
合并所有这些 kie.conf 文件的最佳技巧是在您的 Maven 配置中使用 transformer
,如下所示:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<!-- get all project dependencies -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- MainClass in mainfest make a executable jar -->
<archive>
<manifest>
<mainClass>com.paconsulting.powerpeers.PowerPeersDemo</mainClass>
</manifest>
</archive>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/kie.conf</resource>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
这将创建一个 META-INF/kie.conf
文件,其中包含它找到的任何 kie.conf
文件的内容。
我也遇到过这个错误,但我找到了不同的解决方法。与生成具有所有依赖项的 jar 文件不同,生成具有依赖项库文件夹的 jar 文件是获取可运行 jar 文件的更简单方法。要使用 lib 文件夹生成 jar 文件,请如下所示修改您的 pom.xml 文件。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClassMain-Class</mainClass>
</manifest>
</archive>
</configuration>
</plugin>