2017-10-11 83 views
1

我有一個使用optaplanner的測試程序。沒有直接使用KIE A​​PI,但它看起來像在幕後調用。這可能與我使用DROOLS進行分數計算有關。該程序從IDE或maven工作,但我想創建一個獨立的jar,不需要maven。 我使用maven程序集插件來構建一個包含所有依賴包的獨立運行的胖jar包。例外兒童服務在啓動Optaplanner應用程序時沒有父項

當我運行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> 

在投是有關我的聚甲醛是這樣的:

<?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> 

文件的罐中的完整列表顯示在 https://gist.github.com/wshackle/8887aac8a10e8c4b1f862a4bda288e41

我用grep來驗證他們似乎包括預期的cl驢每個罐子扶養:

> 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 
+0

這從您的IDE工作,對吧?在IDE中它沒有做任何胖子的魔法。 –

+0

@GeoffreyDeSmet對。我相信IDE使用一個長類路徑,其中包含一個帶有裸類文件而不是JAR的目錄。不幸的是,要區分JAR中包含的內容和類路徑中的內容之間的區別並不容易,或者即使是這個問題也是不容易的。 – WillShackleford

+0

[相關jira](https://issues.jboss.org/browse/DROOLS-1761)鏈接到其他2個類似的問題。 –

回答

1

的問題是,下面的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的組裝插件把它們一起META-INF/kie.conf只有一個版本可以被包括在內。當建立求解器時,Optaplanner庫將在當前的線程上下文類加載器上間接調用getResources("META-INF/kie.conf")。如果類路徑中有多個jar,則會找到所有這些jar,並且生成的配置將是解析所有這些jar的產品。爲了使這個工作在一個簡單的超級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); 
1

運行「命令mvn依賴:樹」,你會看到optaplanner核心取決於紀伊的API,紀伊內部的API,流口水核和滴料編譯器。其中一個將會在你的胖罐子裏失蹤。

+0

我添加了問題的文件列表鏈接。所有的依賴似乎都在那裏。 – WillShackleford

1

我是有以下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> 

解決我的問題同樣的問題。希望這可以幫助其他人。

相關問題