tags:

views:

36

answers:

2

I have a multi-project build and in each of the projects I have several packages in the main src tree which need to be packaged up separately from the rest of the src as individual EJB artifacts:

com/foo/ejb/ejb1
com/foo/ejb/ejb2
...

There can be an arbitrary number of these EJBs in each project (0 or several). My question is, how do I create a task that can, per project, Jar each of these as separate artifacts after the regular compile/jar? I.e. So I end up with following artifacts for each project:

project.jar (usual Java classes) 
ejb1.jar (MyEjb1Home/Remote/Bean.class, META_INF/[descriptors])
ejb2.jar (MyEjb2Home/Remote/Bean.class, META_INF/[descriptors])
...

The task(s) should be something I can share to each project (so probably defined in root project) and that will automatically find EJB src and generate a jar for each, without having to explicitly define the EJBs in the subprojects (but perhaps a property set "containsEjbs" to narrow down subprojects that have EJBs).

I'm thinking along the lines of using a filetree to grab the src package (com.foo.ejb.*) and then iterating and Jar-ing - but its how to do this Jar-ing in the context of Tasks which is what I'm having trouble with.

Thanks for any help, Chris.

A: 

You can simply define a new Task of Type: Jar

task('ejb1', type: Jar) {
  //describe jar contents here as a CopySpec
}

This task should automatically be run in the 'assemble' build phase. Full description of features available is at http://www.gradle.org/0.9-rc-1/docs/userguide/userguide_single.html#artifact_management

TheKaptain
thx, but this doesn't describe how to create separate Jars for each arbitrarily named ejb package in each project. Maybe I wasn't clear enough - I want this without having to manually specify the Jar tasks in every project, ie. a routine that automatically finds the ejb packages/directories and then adds tasks for each of these. Thus I can share this logic with all projects without having to write specific tasks to do this for each. I'm getting pretty close now but not sure its the right way...
Chris
If the structure is consistent across each of the subprojects you can configure it once in a parent module and it will be inherited by all. You can also modify/enhance the specific configuration in each of the subprojects as needed using the simple closure syntax, i.e. ejb1 { //configuration goes here in a submodule }
TheKaptain
Yeah thats part of the problem, the structure *isn't* consistent as far as the bottom package is concerned. The top part is: com.foo.ejb - but then the package under this could be anything, e.g. com.foo.ejb.excellentejb and com.foo.ejb.differentejb. I don't want to define anything specific in sub-projects, just an inherited task (or set of generated tasks - the direction I'm heading in) defined in the root project.
Chris
A: 

I ended up doing the following. In [root]/build.gradle:

afterEvaluate { project ->
    if (project.hasProperty('containsEjbs'))
    {
        def basePath = '/com/foo/ejb'
        def classesDir = project.sourceSets.main.classesDir
        def ejbRootClassesDir = file(classesDir.getPath() + basePath)
        def srcFileDirs = project.sourceSets.main.java.srcDirs.collect { file(it.getPath() + basePath) }.findAll { it.exists() && it.isDirectory() }
        def ejbDirs = srcFileDirs.collect { it.listFiles() }.flatten()
        def ejbs = ejbDirs.findAll { it.listFiles().findAll { f -> f.name == 'META-INF'} }
        ejbs.each { file ->
            task "jarEjbFor_$file.name" (type: Jar, dependsOn:classes) {
                baseName = "$file.name"
                classifier = 'ejb'
                from fileTree(file).include('META-INF/**')
                into ("$basePath/$file.name")
                {
                    from fileTree( ejbRootClassesDir.getPath() + "/$file.name" )
                }
            }
        }
    }

So if any projects have a property 'containsEjbs=true', then a tasks is added for each ejb package found under '/com/foo/ejb' in each respective (sub)project. We store META-INF with descriptors in same source tree as classes, so there may be tweaks needed for your set up.

Chris
If there's a more elegant way of doing this, let me know :)
Chris