Gradle设置Manifest Class-Path on Jars in Ear

时间:2014-08-02 17:12:14

标签: gradle classpath ear

设置

我正在使用Gradle并使用Java EE与IBM WebSphere Application Server进行多项目构建。项目目录结构如下所示:

--/build.gradle
--/defaults.gradle
--/settings.gradle
--/common-ejb
--/common-ejb/build.gradle
--/logging
--/logging/build.gradle
--/project1
--/project1/build.gradle
--/project1-ejb
--/project1-ejb/build.gradle
--/project2
--/project2/build.gradle
--/project2-ejb
--/project2-ejb/build.gradle

project1project2是已部署的个人耳朵。它们都重用了common-ejb中的一些EJB,并共享了一些与此问题无关的其他库依赖项。

执行构建后:project1.ear看起来像:

--/lib/log4j.jar
--/lib/logging.jar
--/META-INF/application.xml
--/META-INF/MANIFEST.MF
--/common-ejb.jar
--/project1-ejb.jar

Gradle正确创建application.xml以从两个项目加载EJB。遗憾的是,由于project1-ejb.jar的依赖性,common-ejb.jar将无法加载。 project1-ejb.jar/META-INF/MANIFEST.MF需要Class-Path设置为common-ejb.jar,因为它不在lib/目录中。

我能够通过明确定义它来设置它,如下所示。 Gradle知道Class-Path的依赖关系,因此它应该能够自动执行此操作。有没有办法设置它?

Gradle Files

不包括project2,但你可以猜出它是什么样的。

- /的build.gradle

apply from: 'defaults.gradle'
defaultTasks 'clean', 'build'

- / defaults.gradle

defaultTasks 'build'
repositories {
    mavenCentral()
}

- / settings.gradle

include 'common-ejb'
include 'project1'
include 'project1-ejb'
include 'logging'

- /记录/的build.gradle

apply from: '../defaults.gradle'

apply plugin: 'java'

dependencies {
    compile 'log4j:log4j:1.2.+'
}

- /共EJB /的build.gradle

apply from: '../defaults.gradle'

apply plugin: 'java'

dependencies {
    compile 'javax:javaee-api:6.0'

    compile project(':logging')
}

- / PROJECT1-EJB /的build.gradle

apply from: '../defaults.gradle'

apply plugin: 'java'

dependencies {
    compile 'javax:javaee-api:6.0'

    compile project(':common-ejb')
    compile project(':logging')
}
// THIS IS THE WORKAROUND, I don't want to explicitly modify the Class-Path for each EJB based on the EAR the EJB is going to be included in.
jar {
    manifest {
        attributes("Class-Path": project(':common-ejb').jar.archiveName)
    }
}

- / PROJECT1 /的build.gradle

apply from: '../defaults.gradle'

apply plugin: 'ear'
apply plugin: 'java'

dependencies {
    deploy project(':project1-ejb')
    deploy project(':common-ejb')

    earlib project(':logging')
}

1 个答案:

答案 0 :(得分:0)

从Gradle论坛使用a question about getting all dependencies of a project中的一些信息并修改其中的代码。

基本上,您希望获取EAR的部署依赖关系,并查看是否有任何部署依赖关系相互依赖。如果是这样,则将Class-Path设置为包含引用的jar。

project1-ejbproject2-ejb中删除清单行。将以下内容添加到defaults.gradle:

def getAllDependentProjects(project) {
    if ( !project.configurations.hasProperty("runtime") ) {
        return []
    }
    def projectDependencies = project.configurations.runtime.getAllDependencies().withType(ProjectDependency)
    def dependentProjects = projectDependencies*.dependencyProject
    if (dependentProjects.size > 0) { 
        dependentProjects.each { dependentProjects += getAllDependentProjects(it) }
    }
    return dependentProjects.unique()
}
gradle.projectsEvaluated {
    if (plugins.hasPlugin('ear')) {
        def deployProjectDependencies = configurations.deploy.getAllDependencies().withType(ProjectDependency)*.dependencyProject
        deployProjectDependencies.each {
            def cur = it
            def cur_deps = getAllDependentProjects(cur)
            def depJars = []
            deployProjectDependencies.each {
                def search = it
                if ( cur_deps.contains(search)) {
                    depJars += search.jar.archiveName
                }
            }
            depJars = depJars.unique()
            if ( depJars.size() > 0 ) {
                logger.info("META-INF Dependencies for deploy dependency " + cur.name + ": " + depJars)
                cur.jar.manifest.attributes(
                    'Class-Path': depJars.join(' ')
                )
            }
        }
    }
}

这会产生预期的效果。在配置步骤之后和构建之前,EAR项目将重新评估它们的依赖关系,以查看是否有任何交叉引用。可能有一种更有效的方法,但这可以完成工作。