使用依赖项和测试在Maven中生成jar文件

时间:2018-05-24 11:56:54

标签: java maven jar pom.xml

我在pom.xml中使用此代码来创建一个jar文件。

        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>test.LeanFTest</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </plugin>

我收到错误消息:

  

部署失败:未在POM中指定存储库元素   内部分配

更新

我在pom.xml中添加了另一个插件。

C:.
├───.idea
│   └───libraries
├───META-INF
├───out
│   └───artifacts
│       └───Test_LeanFT_jar
├───resources
│   ├───leanftjar
│   └───META-INF
├───RunResults
│   └───Resources
│       ├───Snapshots
│       └───User
├───src
│   ├───main
│   │   ├───java
│   │   │   ├───com
│   │   │   │   └───myproj
│   │   │   ├───jar
│   │   │   │   └───META-INF
│   │   │   ├───META-INF
│   │   │   ├───unittesting
│   │   │   └───utils
│   │   └───resources
│   └───test
│       └───java
│           └───test
├───target
│   ├───classes
│   │   ├───com
│   │   │   └───myproj
│   │   ├───unittesting
│   │   └───utils
│   ├───generated-sources
│   │   └───annotations
│   ├───generated-test-sources
│   │   └───test-annotations
│   ├───maven-archiver
│   ├───maven-status
│   │   └───maven-compiler-plugin
│   │       ├───compile
│   │       │   └───default-compile
│   │       └───testCompile
│   │           └───default-testCompile
│   ├───surefire
│   ├───surefire-reports
│   │   ├───Command line suite
│   │   ├───junitreports
│   │   └───old
│   │       └───Command line suite
│   └───test-classes
│       └───test
└───test-output
    ├───All Test Suite
    ├───junitreports
    ├───My_Suite
    └───old
        ├───All Test Suite
        └───My_Suite

它会生成一个jar文件,但似乎没有依赖项。

  

线程中的异常&#34; main&#34; java.lang.NoClassDefFoundError:   组织/阿帕奇/ log4j的/记录器

项目结构:

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"> <modelVersion>4.0.0</modelVersion> <groupId>groupId</groupId> <artifactId>LeanFT</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>Mytest</name> <description>Regression test</description> <properties> <leanftsdk>C:/Program Files (x86)/HPE/Unified Functional Testing/SDK/Java/</leanftsdk> <maven.test.skip>true</maven.test.skip> </properties> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.14.3</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> <version>1.3</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>com.hp.lft</groupId> <artifactId>sdk</artifactId> <version>14.0.0</version> <scope>system</scope> <systemPath>${leanftsdk}/com.hp.lft.sdk-standalone.jar</systemPath> </dependency> <dependency> <groupId>com.hp.lft</groupId> <artifactId>report</artifactId> <version>14.0.0</version> <scope>system</scope> <systemPath>${leanftsdk}/com.hp.lft.report.jar</systemPath> </dependency> <dependency> <groupId>com.hp.lft</groupId> <artifactId>unittesting</artifactId> <version>14.0.0</version> <scope>system</scope> <systemPath>${leanftsdk}/com.hp.lft.unittesting.jar</systemPath> </dependency> <dependency> <groupId>com.hp.lft</groupId> <artifactId>verifications</artifactId> <version>14.0.0</version> <scope>system</scope> <systemPath>${leanftsdk}/com.hp.lft.verifications.jar</systemPath> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>1.10</version> <executions> <execution> <id>add-source</id> <phase>generate-sources</phase> <goals> <goal>add-source</goal> </goals> <configuration> <sources> <source>appmodels</source> </sources> </configuration> </execution> </executions> </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>test.LeanFTest</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skipTests>true</skipTests> </configuration> </plugin> </plugins> </build> </project> 档案:

import React from 'react'
import { render } from 'react-dom'

const ErrorOutput = props => {
  let name = props.name
  let inputValue = props.case
  let submit = props.submit
  // Data validation
  if (name === 'firstName') {
    if (!inputValue.match(/^[a-zA-Z]+$/) && inputValue.length > 0) {
        return <span>Letters only</span>
      } else if (submit && inputValue.length === 0) {
        return <span>Required</span>
      }
    return <span></span>
  }
  if (name === 'telNo') {
    if(!inputValue.match(/^[0-9]+$/) && inputValue.length > 0) {
        return <span>Numbers only</span>
      } else if (submit && inputValue.length === 0) {
        return <span>Required</span>
      }
    return <span></span>
  }
}

class App extends React.Component {
  constructor(props){
    super(props)

    this.state = {
      firstName: '',
      telNo: '',
      submit: false
    }
  }

  handleSubmit(e){
    e.preventDefault()
    let submit = true
    let error = true
    const { firstName, telNo } = this.state
    this.setState ({submit: submit})

    // Repeat the data validation before submission
    if (firstName === '' || !firstName.match(/^[a-zA-Z]+$/)) {
      error = true
    } else if (telNo === '' || !telNo.match(/^[0-9]+$/)) {
      error = true
    } else {
      error = false
    }

    // Submited if all data is valid
    if (!error) {
      // send data
      return alert('Success!')
    }
  }

  handleValidation(e) {    
    this.setState({
      [e.target.name]: e.target.value 
    })  
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit.bind(this)}>
        <div>
          <label>
            First name:
          </label>
          <input
            type='text'
            name ='firstName'
            value = {this.state.firstName}
            onChange = {this.handleValidation.bind(this)}
          />
          <ErrorOutput case={this.state.firstName} name={'firstName'} submit = {this.state.submit} />
        </div>
        <div>
          <label>
            Phone number:
          </label>
          <input
            type='tel'
            name ='telNo'
            value = {this.state.telNo}
            onChange = {this.handleValidation.bind(this)}
          />
          <ErrorOutput case={this.state.telNo} name={'telNo'} submit = {this.state.submit} />
        </div>
        <button>
          Submit
        </button> 
      </form>
    )
  }
}

render(
  <App />,
  document.getElementById('root')
)

3 个答案:

答案 0 :(得分:5)

我的解决方案是构建一个存档(zip或其他格式),其中包含jar中的类,依赖项jar,带有运行时配置文件的文件夹和启动应用程序的脚本。范围是通过解压缩存档来运行就绪应用程序。

构建的存档内容为:

artifactId-version.zip:
<artifactId folder>
    ├─ config
    |    ├─ log4j2.xml
    ├─ lib
    |    ├─ <all dependencies jars>
    ├─ leanft.cmd
    ├─ leanft.sh
    └─ artifactId-version.jar

您应该根据您需要的配置文件来定制解决方案。您不需要带有MANIFEST.MF文件的META-INF文件夹,因为它将由maven插件自动生成。

项目结构

<maven_module_root>
├─ src
|   ├─ main
|   |    ├─ assembly
|   |    |    ├─ leanft-assembly.xml
|   |    ├─ java
|   |    |    ├─ <your classes content>
|   |    ├─ resources
|   |    |    ├─ log4j2.xml
|   |    |    ├─ <your runtime configuration files>
|   |    ├─ scripts
|   |    |    ├─ leanft.cmd
|   |    |    ├─ leanft.sh
│   └───test
├─ pom.xml

项目结构与您当前的结构类似,另外还有两个文件夹:
- assembly:在这个文件夹中是leanft-assembly.xml来定制maven-assembly-plugin - scripts:在此文件夹中是应用程序的启动程序脚本。如果您需要可用于编辑的运行时配置文件,则必须执行此操作。在我的示例中,resources / log4j2.xml将位于配置文件中,因此用户可以编辑此文件而无需触及任何jar / archive。

程序集描述符

该解决方案基于具有自定义配置的maven程序集插件。我建议从描述符assembly descriptor

开始熟悉它

您的leanft-assembly.xml可能如下所示:

<assembly
    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
    <id>dist</id>
    <formats>
        <!-- <format>tar.gz</format> -->
        <format>zip</format>
    </formats>
    <includeBaseDirectory>true</includeBaseDirectory>
    <baseDirectory>${project.artifactId}</baseDirectory>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>${project.artifactId}-${project.version}.jar</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/lib</directory>
            <outputDirectory>/lib</outputDirectory>
            <includes>
                <include>*.*</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.outputDirectory}</directory>
            <outputDirectory>/config</outputDirectory>
            <includes>
                <include>log4j2.xml</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.basedir}/src/main/scripts</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>leanft.*</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>

Maven pom

最后,pom.xml使用了3个插件:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>3.0.1</version>
        <executions>
            <execution>
                <id>copy-dependencies</id>
                <phase>package</phase>
                <goals>
                    <goal>copy-dependencies</goal>
                </goals>
                <configuration>
                    <outputDirectory>${project.build.directory}/lib</outputDirectory>
                    <overWriteIfNewer>true</overWriteIfNewer>
                    <overWriteReleases>false</overWriteReleases>
                    <overWriteSnapshots>true</overWriteSnapshots>
                </configuration>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.0.2</version>
        <configuration>
            <archive>
                <manifest>
                    <addClasspath>true</addClasspath>
                    <classpathPrefix>lib/</classpathPrefix>
                    <mainClass>test.LeanFTest</mainClass>
                </manifest>
            </archive>
            <excludes>
                <exclude>log4j2.xml</exclude>
            </excludes>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
            <execution>
                <id>make-assembly</id>
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <finalName>${project.artifactId}-${project.version}</finalName>
            <appendAssemblyId>false</appendAssemblyId>
            <descriptors>
                <descriptor>src/main/assembly/leanft-assembly.xml</descriptor>
            </descriptors>
        </configuration>
    </plugin>

我将解释maven插件的用法:
- maven-dependency-plugin:在目标文件夹下的lib文件夹中复制包阶段的所有依赖项 - maven-jar-plugin:
- archive:生成清单文件,在清单中定义lib文件夹中的所有依赖项以及主类是什么,这样你就可以使用“java -jar”运行应用程序了 - 排除:不要在模块jar中包含log4j2.xml文件,因为它将位于运行时从jar外部的config文件夹中。 - maven-assembly-plugin:在包阶段创建一个包含您的发行版的zip文件。存档放在目标文件夹中。描述符标记引用您的程序集配置文件leanft-assembly.xml。

脚本

启动应用程序的脚本使用预定义参数调用java,脚本的主线为:

%JAVA_HOME%\bin\java %JVM_ARGS% -cp %SCRIPT_DIR%\*;%SCRIPT_DIR%\config\ test.LeanFTest

答案 1 :(得分:3)

要创建一个超级jar(如评论中所阐明的),可以使用Maven Shade插件。该插件将生成一个JAR,其中包含项目类以及依赖项JAR中的所有类。

注意:具有预定义jar-with-dependencies的Maven程序集插件将生成一个带有固定分类器(jar-with-dependencies)的超级jar,紧邻未分类的jar。似乎无法覆盖它(除了定义自定义程序集)。

答案 2 :(得分:3)

您需要在maven-assembly-plugin中指定执行阶段。使用以下maven-assembly-plugin配置。

     <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
            <archive>
                <manifest>
                    <mainClass>test.LeanFTest</mainClass>
                </manifest>
            </archive>
            <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
        </configuration>
        <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
        </executions>
    </plugin>

现在只需在项目 pom.xml (根目录)上运行mvn package,您就可以通过artifactId和#34; jar-with-dependencies&#获得完全组装的jar 34;后缀。