3

I am trying to use the maven-antrun-plugin to copy generated .java files to my current source directory. My problem is that one part of the path directory I want to copy is generated.

The path I want to copy look like this :

${project.build.directory}/working/<GENERATED_DIRECTORY_I_DONT_KNOW_THE_NAME>/${project.artifactId}-${project.version}/ejbModule

and from this point I want to copy all .java files with its subdirectories (to keep the tree of the packages.

See my above plugin configuration :

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <executions>
        <execution>
            <id>ejbdeploy-copy</id>
            <phase>verify</phase>
            <goals>
                <goal>run</goal>
            </goals>
            <configuration>
                <tasks>
                    <echo>Moving stubs file to source project.</echo>
                    <copy todir="${project.build.sourceDirectory}">
                        <fileset dir="${project.build.directory}/working/**/${project.artifactId}-${project.version}/ejbModule">
                            <include name="**/*.java"/>
                        </fileset>
                    </copy>
                </tasks>
            </configuration>
        </execution>
    </executions>
</plugin>

The thing is that the maven-antrun-plugin cannot convert my ** to the generated directory name.

I tried with this kind of configuration but it didn't work :

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <executions>
        <execution>
            <id>ejbdeploy-copy</id>
            <phase>verify</phase>
            <goals>
                <goal>run</goal>
            </goals>
            <configuration>
                <tasks>
                    <echo>Moving stubs file to source project.</echo>
                    <copy todir="${project.build.sourceDirectory}">
                        <fileset dir="${project.build.directory}">
                            <include name="**/*.java"/>
                            <exclude name="**/ejbModule/"/>
                        </fileset>
                    </copy>
                </tasks>
            </configuration>
        </execution>
    </executions>
</plugin>

Any ideas ?

Stéphane GRILLON
  • 11,140
  • 10
  • 85
  • 154
MadJlzz
  • 767
  • 2
  • 13
  • 35
  • What is the intention of copying source files in the `verify` phase? – Little Santi Sep 12 '16 at 10:44
  • Beware because this is a very old project. The thing is that I need to launch ejbdeploy to generate some stubs for remote EJB (2.1) To do so, I need to launch the ejbdeploy command on the jar I just created in the package phase of my module. After that am I only able to copy all of my generated .java files. I am just forced to plug my plugin on a phase after the package one. That's why. – MadJlzz Sep 12 '16 at 10:48

2 Answers2

2

You are going at it the wrong way. You definitely do not want to copy source files into your main source directory. Generated files should never end up in src/main/java. This is because generated code must not be version-controled; those are files that are re-generated during the build, and, thus, should always be located inside the build directory of Maven, which is target by default.

To add those files as sources, instead of copying them into the main source directory, you can use the build-helper-maven-plugin:add-source goal. This will add a specified folder as a source directory. In this case, you can use it and refer to the generated folder containing your sources.

The trick is that you do not know the path to the folder. To tackle this, you can make use of the iterator-maven-plugin. With this plugin, you can iterate over all subdirectories of a given directory; the current directory can be obtained with the variable @item@. This way, the configuration is dynamic with regard to the name of the directory.

<plugin>
  <groupId>com.soebes.maven.plugins</groupId>
  <artifactId>iterator-maven-plugin</artifactId>
  <version>0.4</version>
  <executions>
    <execution>
      <phase>generate-sources</phase>
      <goals>
        <goal>iterator</goal>
      </goals>
      <configuration>
        <folder>${project.build.directory}/working</folder>
        <pluginExecutors>
          <pluginExecutor>
            <plugin>
              <groupId>org.codehaus.mojo</groupId>
              <artifactId>build-helper-maven-plugin</artifactId>
              <version>1.12</version>
            </plugin>
            <goal>add-source</goal>
            <configuration>
              <sources>
                <source>${project.build.directory}/working/@item@/${project.artifactId}-${project.version}/ejbModule</source>
              </sources>
            </configuration>
          </pluginExecutor>
        </pluginExecutors>
      </configuration>
    </execution>
  </executions>
</plugin>
Tunaki
  • 132,869
  • 46
  • 340
  • 423
  • I agree with you but your solution won't work for me here. This is because the generated source files comes from the ejbdeploy command launched on the jar I've just built. I am forced to put it on a phase after package. Despite of that, I am going to try your solution. Is Eclipse gonna add this folder to the build path after that ? – MadJlzz Sep 12 '16 at 11:50
  • @MadJlzz Why do you want to add source files at the package phase? At that time, the code was already compiled, so they won't be taken into account. The `ejbdeploy` executable, that is generating the sources, should also be launched at the `generate-sources` phase. – Tunaki Sep 12 '16 at 11:53
  • Because ejbdeploy executable need the jar made of my compiled source to generate a new one with the EJB remote stubs inside. They are compiled with RMIC so it's all fine. I'am trying to do this because without these source files I can't use my application properly. When I deploy my application, I need to have this files sourced or the application won't work at all. (I am deploying it using RAD on a Websphere.) This is because RAD doesn't deploy to WAS the final EAR that I've built but do instead some kind of black magic to make things work. – MadJlzz Sep 12 '16 at 12:14
  • @MadJlzz I see. Consider making a multi-module Maven project and having a module that will package the JAR needed to run `ejbdeploy`. Then in another module, you can depend on that first module, execute `ejbdeploy` in the generate-sources phase and add the created sources as source folder in generate-sources also. – Tunaki Sep 12 '16 at 13:50
  • As told to @Little Santi, I gave up on doing weirds stuff with Maven since this is only a RAD problem. Maven has no right to do something to make RAD happy so I've updated my version of RAD and everything is working out of the box now. Thanks. The solution is not in your answer but if you don't mind, I'll accept yours as this is the right thing to do Mavenly speaking. – MadJlzz Sep 14 '16 at 11:10
0

Immediate solution: Set the generated directory name as a property:

<fileset dir="${project.build.directory}/working/${generated.dir}/${project.artifactId}-${project.version}/ejbModule">
    <include name="**/*.java"/>
</fileset>

The variable might be declared either in the properties section of the pom, either in some profile the local settings.xml file, or either be received directly from command line:

mvn -Dgenerated.dir=c:\generated clean install

Update

If the generated directory is just one, you can get its name by a simple program in Ant. I recommend you to take all the ant stuff to a build.xml file:

<project basedir=".">
    <dirset id="dirs" dir="${project.build.directory}/working" includes="*" />
    <pathconvert pathsep="${line.separator}" property="generated.dir" refid="dirs">
        <chainedmapper>
            <mapper type="flatten" />
            <regexpmapper from="(.*)" to="\1" />
        </chainedmapper>
    </pathconvert>
    <echo>Moving stubs file from ${generated.dir} to source project.</echo>
    <copy todir="${project.build.sourceDirectory}">
        <fileset dir="${project.build.directory}/working/${generated.dir}/${project.artifactId}-${project.version}/ejbModule">
            <include name="**/*.java" />
        </fileset>
    </copy>
</project>

Then, it's just call it from the pom:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.8</version>
            <executions>
                <execution>
                    <id>ejbdeploy-copy</id>
                    <phase>verify</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                    <configuration>
                        <tasks>
                            <ant antfile="build.xml">
                            </ant>
                        </tasks>
                    </configuration>
                </execution>
            </executions>
        </plugin>

Important: Respect version 1.8 of maven-antrun-plugin.

Little Santi
  • 8,563
  • 2
  • 18
  • 46
  • This cannot be a solution since I do not know by advance the name of the generated directory. – MadJlzz Sep 12 '16 at 11:43
  • Tunaki's point is well taken: It is not a good practice to copy generated files to `src` directory. Tough it is not possible to add a source nor resource directory because you don't know the name of the generated dir before the `compile` phase, you should copy your generated files to the `target/classes` dir instead. – Little Santi Sep 13 '16 at 09:01
  • This is not about good practice or not ; I know this is completely dirty and should not be done. This project has 13 years old and had no Maven structure until now. Everything cannot be done as if I started from the beginning. Anyway, I choose to give up on that since Maven has no right to do things in order to make RAD happy. I upgraded my version of RAD and everything works out of the box now. Thanks. – MadJlzz Sep 14 '16 at 11:08