Optaplanner - 创建jar文件

时间:2017-09-13 13:50:27

标签: java jar nullpointerexception optaplanner

我的程序在我的IDE(IntelliJ)中工作正常,但出于某种原因,当我尝试创建一个jar文件时,从终端运行程序时出现以下错误:

  

线程中的异常" main" org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildDroolsScoreDirectorFactory(ScoreDirectorFactoryConfig.java:461)中的java.lang.NullPointerException

     

org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildScoreDirectorFactory(ScoreDirectorFactoryConfig.java:331)

     

org.optaplanner.core.config.solver.SolverConfig.buildSolver(SolverConfig.java:220)

     

org.optaplanner.core.impl.solver.AbstractSolverFactory.buildSolver(AbstractSolverFactory.java:57)

     

org.optaplanner.EmployeeRoster.main(EmployeeRoster.java:31)

这是我在EmployeeRoster中的第31行:

Solver solver = SolverFactory.createFromXmlResource(SOLVER_CONFIG_XML).buildSolver();

SOLVER_CONFIG_XML是一个String,包含我的XML solver-config的路径, 看起来像这样



<?xml version="1.0" encoding="UTF-8"?>
<solver>
	<solutionClass>org.optaplanner.solver.Roster</solutionClass>
	<entityClass>org.optaplanner.domain.Assignment</entityClass>
	<scoreDirectorFactory>
		<scoreDrl>org/optaplanner/solver/employeeShiftsScoreRules.drl</scoreDrl>
	</scoreDirectorFactory>
	<localSearch>
		<termination>
			<secondsSpentLimit>5</secondsSpentLimit>
			<bestScoreLimit>0hard/0medium/0soft</bestScoreLimit>
		</termination>
		<!--<termination>
			<unimprovedStepCountLimit>5</unimprovedStepCountLimit>
		</termination>-->
		<acceptor>
			<entityTabuSize>7</entityTabuSize>
		</acceptor>
		<forager>
			<acceptedCountLimit>1000</acceptedCountLimit>
		</forager>
	</localSearch>
</solver>
&#13;
&#13;
&#13;

此处还有我的pom.xml文件,如果它应该是相关的:

<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>org.btrg.dfb</groupId>
<artifactId>optaplanner</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
    <dependency>
        <groupId>org.optaplanner</groupId>
        <artifactId>optaplanner-core</artifactId>
        <version>7.3.0.Final</version>
    </dependency>

    <dependency>
        <groupId>com.thoughtworks.xstream</groupId>
        <artifactId>xstream</artifactId>
        <version>1.4.8</version>
    </dependency>

    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.1</version>
    </dependency>

    <dependency>
        <groupId>com.jolira</groupId>
        <artifactId>onejar-maven-plugin</artifactId>
        <version>1.4.4</version>
    </dependency>

</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>

        <plugin>
            <!-- Build an executable JAR -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>org.avalin.optaplanner.EmployeeRoster</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-my-jar-with-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

        <plugin>
            <groupId>com.jolira</groupId>
            <artifactId>onejar-maven-plugin</artifactId>
            <version>1.4.4</version>
            <executions>
                <execution>
                    <goals>
                        <goal>one-jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

我可能做错了什么?

2 个答案:

答案 0 :(得分:4)

对我来说,问题必须处理我想要运行jar的方式( java -jar ),以及我如何构建jar。当我从 6.4.0 升级到 optaplanner-core / 7.4.1 时,出现NullPointerException。当我还在使用6.4.0时,这个问题不存在了。

例外:

  

显示java.lang.NullPointerException       在org.kie.internal.io.ResourceFactory.newByteArrayResource(ResourceFactory.java:66)       at org.drools.compiler.kie.builder.impl.AbstractKieModule.getResource(AbstractKieModule.java:299)       at org.drools.compiler.kie.builder.impl.AbstractKieModule.addResourceToCompiler(AbstractKieModule.java:264)       at org.drools.compiler.kie.builder.impl.AbstractKieModule.addResourceToCompiler(AbstractKieModule.java:259)       at org.drools.compiler.kie.builder.impl.AbstractKieProject.buildKnowledgePackages(AbstractKieProject.java:243)       at org.drools.compiler.kie.builder.impl.AbstractKieProject.verify(AbstractKieProject.java:74)       在org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildKieProject(KieBuilderImpl.java:250)       在org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildAll(KieBuilderImpl.java:218)       在org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildAll(KieBuilderImpl.java:176)       在org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildDroolsScoreDirectorFactory(ScoreDirectorFactoryConfig.java:503)

以下是临时解决方法我解决NullPointerException并让应用程序运行。

  1. 使用IntelliJ的gradle构建一个包含所有依赖项的大jar。
  2. 将jar解压缩到 unzippedJar / 目录。
  3. 修改 unzippedJar / META-INF / kie.conf
  4. Rejar文件。
  5. 使用java运行jar。
  6. 步骤1.构建jar

    dependencies {
        ...
        compile group: 'org.optaplanner', name: 'optaplanner-core', version:'7.4.1.Final'
        compile group: 'org.optaplanner', name: 'optaplanner-benchmark', version:'7.4.1.Final'
        ...
    }
    task fatJar(type: Jar) {
        manifest {
            attributes 'Implementation-Title': 'Self contained jar with all dependencies',
            'Implementation-Version': version,
            'Main-Class': 'path.to.class.with.main.method'
        }
        baseName = 'fatJar'
        from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
        with jar
    }
    

    步骤2.解压缩

    unzip fatJar.jar -d unzippedJar/

    步骤3.修改kie.conf

    “fatJar”任务压平了依赖项 - jar中允许使用重复的文件名。这导致了四个 unzippedJar / META-INF / kie.conf 文件,其中只使用了其中一个。无论使用哪个kie.conf文件,这都是我最后的kie.conf。

        org.kie.api.internal.assembler.KieAssemblers = +org.optaplanner.core.impl.solver.kie.KieSolverAssemblerService
        org.kie.api.internal.assembler.KieAssemblers = org.kie.internal.services.KieAssemblersImpl
        org.kie.api.internal.runtime.KieRuntimes = org.kie.internal.services.KieRuntimesImpl
        org.kie.api.internal.weaver.KieWeavers = org.kie.internal.services.KieWeaversImpl
        org.kie.api.internal.runtime.beliefs.KieBeliefs = org.kie.internal.services.KieBeliefsImpl
        org.kie.api.io.KieResources = org.drools.core.io.impl.ResourceFactoryServiceImpl
        org.kie.api.marshalling.KieMarshallers = org.drools.core.marshalling.impl.MarshallerProviderImpl
        org.kie.api.concurrent.KieExecutors = org.drools.core.concurrent.ExecutorProviderImpl
        org.kie.api.KieServices = org.drools.compiler.kie.builder.impl.KieServicesImpl
        org.kie.internal.builder.KnowledgeBuilderFactoryService = org.drools.compiler.builder.impl.KnowledgeBuilderFactoryServiceImpl
    

    步骤4. Rejar

    无论出于何种原因,指定MANIFEST.MF文件对我没有任何作用,因此我将其删除了。

    jar cf rejard.jar .

    步骤5.运行jar

    java -cp rejard.jar path.to.class.with.main.method

答案 1 :(得分:2)

在@Arturo W的回答之后,我可以建议使用maven's assembly plugin进行另一种修复 制作一个胖子罐。

documentation中所述:

  

”如果两个或多个元素(例如file,fileSet)选择了不同的来源   如果要归档同一文件,则仅归档其中一个源文件。   [...]阶段的顺序如下:1)FileItem 2)FileSets   3)ModuleSet 4)DependencySet和5)Repository元素。”

META-INF/kie.conf位于org.optaplanner.core的档案中,因此 Maven将optaplanner的版本打包到您定义的自定义版本中 存储库。

要包含此文件,我们在解包过程中会排除所有META-INF/kie.conf个文件 并使用<file></file>手动复制我们的版本 自定义描述符文件中的选项。

这是我们的操作方式:

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">
    <!-- ... -->
    <build>
        <plugins>
            <!-- ... -->

            <!-- fat jar -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <descriptors>
                        <descriptor>src/assembly/distribution.xml</descriptor>
                    </descriptors>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>com.veryseriouscompany.veryseriousproject.app.Main</mainClass>
                        </manifest>
                    </archive>

                </configuration>
                <executions>
                    <execution>
                        <id>assemble-all</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <!-- ... -->

要修复包含kie.conf的问题,我们必须编写一个自定义描述符, 在src/assembly/distribution.xml中定义。我们从预定义开始 描述符: jar-with-dependencies。 这是一个很好的起点。

src / assembly / distribution.xml

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
    <id>epigno-jar-with-dependencies</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>runtime</scope>
            <!-- Exclude all META-INF/kie.conf during unpacking -->
            <unpackOptions>
                <excludes>
                    <exclude>META-INF/kie.conf</exclude>
                </excludes>
            </unpackOptions>
        </dependencySet>
    </dependencySets>
    <files>
        <file>
            <!-- Manually copy your custom kie configuration file from your repository. -->
            <!-- Please replace this path by whatever path is relevant for your project. -->
            <source>src/main/resources/META-INF/kie.conf</source>
            <outputDirectory>META-INF</outputDirectory>
        </file>
    </files>
</assembly>

完成后,运行

mvn package

希望这会将正确的kie.conf包装在您的胖子罐中!