216

Is there a way to compile multiple java source directories in a single maven project?

sal
  • 23,373
  • 15
  • 66
  • 85

10 Answers10

296

You can add a new source directory with build-helper:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>3.2.0</version>
            <executions>
                <execution>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>add-source</goal>
                    </goals>
                    <configuration>
                        <sources>
                            <source>src/main/generated</source>
                        </sources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277
  • 4
    The only issue with this approach is that the final artifact includes the java source files as well(.java files). Is there a way to exclude the source files and include only have the .class files? – saravana_pc Sep 05 '12 at 09:23
  • 19
    just a note for others (like me), `plugin` element is in `/project/build/plugins` and NOT in `/project/build/pluginManagement/plugins` – Betlista Sep 10 '12 at 09:20
  • So if (in Eclipse Luna) i added (linked) in my BuildPath (clicking the right mouse button on my MavenProject) a source folder where its directory is "/Users/MyName/Desktop/source", i have to write `/Users/MyName/Desktop/source` ?? And everything goes right? – Aerox Apr 29 '15 at 18:03
  • If you also have tests in a seperate source folder (e.g. src/test) , do not forget to also add your generaged sources to the test-compile. You can do this, by adding another `` with the `add-test-source` and `generate-test-sources`. – Peter Ittner Jul 10 '15 at 06:59
  • 3
    If you are using eclipse, you might want to install `m2e connector for build-helper-maven-plugin` from eclipse marketplace to remove the error in pom.xml – dieend Sep 23 '15 at 07:57
  • 1
    If you receive a warning like `'build.plugins.plugin.version' for org.codehaus.mojo:build-helper-maven-plugin is missing` you need to add within `` the tag `1.12` – Alphaaa Oct 20 '16 at 11:47
  • This worked and was understood by IDEA Maven project import. I had to try reimport in IDEA a couple times to get IDEA module structure updated. – Dima Korobskiy Jun 20 '17 at 19:39
  • This worked for me with Maven 3.5.2, but I had to set it to `validate`. – Kent Aug 06 '18 at 21:08
  • 9
    So the best way to do this, in 2017, was to create an XML pasta. Does nobody see a problem with that? – Tom Oct 11 '18 at 04:25
  • @saravana_pc I only have class files (no .java files) in final artifact. (build-helper-maven-plugin 3.0.0) – bjmi Feb 09 '20 at 09:51
  • @Tom I don't like too much XML pasta. It is really filling. – Jonathan Locke Jun 01 '21 at 19:32
65

I naively do it this way :

<build>
  <finalName>osmwse</finalName>
  <sourceDirectory>src/main/java, src/interfaces, src/services</sourceDirectory>
</build>
comeGetSome
  • 1,913
  • 19
  • 20
  • 3
    Worked for me to :) Eclipse doesn't seem to like it though. It seems to think "src/main/java, src/interfaces" is a single src, and therefore flags it as (missing). – Joel Sep 10 '16 at 19:29
  • 5
    For me, that caused Maven 3.2.2 not to find any sources. – user149408 Apr 30 '20 at 21:49
  • I got similar experience as @Joel, Code compiled but had problems with things like recognizing a "main" method. – John Apr 13 '21 at 23:46
  • 4
    For maven 3.8.1 does not work. Also, in the documentation for this version of the maven, nowhere is it written that such a content is possible in the tag . --- maven-compiler-plugin:3.8.1:compile (default-compile) @ xxx-xxx --- No sources to compile – Eliahu May 31 '21 at 10:24
  • Worked in netbeans and did not break intelliJ, or Eclipse for me. – user1133275 Dec 15 '21 at 05:56
  • Can someone point me to documentation that mention that we can use multiple directories separated by comma in – AhmedRana Dec 01 '22 at 20:45
46

This worked for me

<build>
    <sourceDirectory>.</sourceDirectory>
    <plugins>
        <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
        <includes>
            <include>src/main/java/**/*.java</include>
            <include>src/main2/java/**/*.java</include>
        </includes>
        </configuration>
        </plugin>
    </plugins>
</build>
Betlista
  • 10,327
  • 13
  • 69
  • 110
sal
  • 23,373
  • 15
  • 66
  • 85
  • 21
    Not such a good idea IMHO, since several plugins assume the `sourceDirectory` - and possibly additional `sources` - as the roots of source files. In your solution, the `maven-compiler-plugin` is the only plugin aware of these actual roots. – Laurent Pireyn May 04 '11 at 14:17
  • 3
    @Laurent You're right about that. This was a good idea a couple years ago but there are much better options now. build-helper listed above is my preferred options. – sal May 06 '11 at 01:51
  • 5
    This doesn't add it to the project model, so it won't work correctly in IDEs. – David Phillips Nov 10 '11 at 20:29
  • +1 @sal it worked like a charm with a WAR project dependency. – ATorras Dec 28 '11 at 09:01
  • 1
    This cannot work if i want to include an external source directory (containing Java class that i'm using in my maven project). What if my external source is located outside my Eclipse's workspace? What can i do? – Aerox May 01 '15 at 15:05
  • Worked for me on Maven 3.5.4 – Cesar Moore Mar 18 '19 at 19:53
25

To make it work in intelliJ, you can also add generatedSourcesDirectory to the compiler plugin this way:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <generatedSourcesDirectory>src/main/generated</generatedSourcesDirectory>
    </configuration>
</plugin>
cb4
  • 6,689
  • 7
  • 45
  • 57
domi.vds
  • 267
  • 3
  • 2
  • Would like to add that this worked in Eclipse as well to add the generated sources as a source location in the project configuration. – Adam Hawkes Aug 14 '13 at 16:58
  • 3
    This path seems to be for sources generated by annotation processors though. Even if it works, it is possible that this path is handled differently by some plugins. For example I would expect this directory could be deleted when 'clean' is run. – kapex Mar 06 '18 at 10:55
  • 2
    where did you put it ? – Pavel Niedoba Sep 05 '18 at 12:46
  • **IntelliJ 2021.2.3** This still works and it was the only solution I found that did. I agree with @kapex that it is intended for annotations, but I spent a day trying to find the "right way" to do it and failed. – cb4 Dec 12 '21 at 22:09
  • To make the build less brittle and more in line with maven standards:`${project.build.directory}/generated-sources/main/java` – cb4 Dec 12 '21 at 22:18
9

This also works with maven by defining the resources tag. You can name your src folder names whatever you like.

    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.java</include>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
        </resource>

        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.java</include>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
        </resource>

        <resource>
            <directory>src/main/generated</directory>
            <includes>
                <include>**/*.java</include>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
Gavin S. Yancey
  • 1,216
  • 1
  • 13
  • 34
sendon1982
  • 9,982
  • 61
  • 44
  • 12
    http://maven.apache.org/pom.html#Resources --> `Resources are not (usually) code. They are not compiled` – SJuan76 Sep 08 '15 at 14:57
7

This worked for with maven 3.5.4 and now Intellij Idea see this code as source:

<plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-compiler-plugin</artifactId>
     <version>3.3</version>
     <configuration>
         <generatedSourcesDirectory>src/main/generated</generatedSourcesDirectory>                    
     </configuration>
</plugin>
SwissCodeMen
  • 4,222
  • 8
  • 24
  • 34
Maksym
  • 2,650
  • 3
  • 32
  • 50
4

While the answer from evokk is basically correct, it is missing test classes. You must add test classes with goal add-test-source:

<execution>
    <phase>generate-sources</phase>
    <goals>
        <goal>add-test-source</goal>
    </goals>
    <configuration>
       <sources>
            <source>target/generated/some-test-classes</source>
        </sources>
    </configuration>
</execution>
SwissCodeMen
  • 4,222
  • 8
  • 24
  • 34
radzimir
  • 1,178
  • 13
  • 10
2

Used the build-helper-maven-plugin from the post - and update src/main/generated. And mvn clean compile works on my ../common/src/main/java, or on ../common, so kept the latter. Then yes, confirming that IntelliJ IDEA (ver 10.5.2) level of the compilation failed as David Phillips mentioned. The issue was that IDEA did not add another source root to the project. Adding it manually solved the issue. It's not nice as editing anything in the project should come from maven and not from direct editing of IDEA's project options. Yet I will be able to live with it until they support build-helper-maven-plugin directly such that it will auto add the sources.

Then needed another workaround to make this work though. Since each time IDEA re-imported maven settings after a pom change me newly added source was kept on module, yet it lost it's Source Folders selections and was useless. So for IDEA - need to set these once:

  • Select - Project Settings / Maven / Importing / keep source and test folders on reimport.
  • Add - Project Structure / Project Settings / Modules / {Module} / Sources / Add Content Root.

Now keeping those folders on import is not the best practice in the world either, ..., but giving it a try.

arntg
  • 1,557
  • 14
  • 12
  • Neither option works with IntelliJ Idea 9.0.4 which is what I use. Haven't tried the build-helper options with the recent Eclipse, but it didn't work with 3.4 and the m2 plugin when I tried it. Maven doesn't like multiple source trees or multiple artifacts built from the same project any any attempt to get around this limitation is usually an awful hack. – sal Nov 11 '11 at 14:16
  • Have been on IntelliJ for many years now. And never switched to eclipse, so can't talk for it, then hearing it's generally very good too. For IntelliJ Upgrading a personal license every other year is at $100/year. The new major versions are usually out every year at January. Then at the last 2-3 month of previous year they are allowing you to buy the previous version and get the upgrade to the upcoming one free. This is on right now so it's the "safe" time to buy 10 and get 11. Also, if you don't need JSP and other enterprise features, use the free community edition. – arntg Nov 11 '11 at 17:16
1

This can be done in two steps:

  • For each source directory you should create own module.
  • In all modules you should specify the same build directory: ${build.directory}

If you work with started Jetty (jetty:run), then recompilation of any class in any module (with Maven, IDEA or Eclipse) will lead to Jetty's restart. The same behavior you'll get for modified resources.

Gerold Broser
  • 14,080
  • 5
  • 48
  • 107
ursa
  • 4,404
  • 1
  • 24
  • 38
1

In the configuration, you can use <compileSourceRoots>.

oal:          org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-cli)
[DEBUG] Style:         Regular
[DEBUG] Configuration: <?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <basedir default-value="${basedir}"/>
  <buildDirectory default-value="${project.build.directory}"/>
  <compilePath default-value="${project.compileClasspathElements}"/>
  <compileSourceRoots default-value="${project.compileSourceRoots}"/>
  <compilerId default-value="javac">${maven.compiler.compilerId}</compilerId>
  <compilerReuseStrategy default-value="${reuseCreated}">${maven.compiler.compilerReuseStrategy}</compilerReuseStrategy>
  <compilerVersion>${maven.compiler.compilerVersion}</compilerVersion>
  <debug default-value="true">${maven.compiler.debug}</debug>
  <debuglevel>${maven.compiler.debuglevel}</debuglevel>
  <encoding default-value="${project.build.sourceEncoding}">${encoding}</encoding>
  <executable>${maven.compiler.executable}</executable>
  <failOnError default-value="true">${maven.compiler.failOnError}</failOnError>
  <failOnWarning default-value="false">${maven.compiler.failOnWarning}</failOnWarning>
  <forceJavacCompilerUse default-value="false">${maven.compiler.forceJavacCompilerUse}</forceJavacCompilerUse>
  <fork default-value="false">${maven.compiler.fork}</fork>
  <generatedSourcesDirectory default-value="${project.build.directory}/generated-sources/annotations"/>
  <maxmem>${maven.compiler.maxmem}</maxmem>
  <meminitial>${maven.compiler.meminitial}</meminitial>
  <mojoExecution default-value="${mojoExecution}"/>
  <optimize default-value="false">${maven.compiler.optimize}</optimize>
  <outputDirectory default-value="${project.build.outputDirectory}"/>
  <parameters default-value="false">${maven.compiler.parameters}</parameters>
  <project default-value="${project}"/>
  <projectArtifact default-value="${project.artifact}"/>
  <release>${maven.compiler.release}</release>
  <session default-value="${session}"/>
  <showDeprecation default-value="false">${maven.compiler.showDeprecation}</showDeprecation>
  <showWarnings default-value="false">${maven.compiler.showWarnings}</showWarnings>
  <skipMain>${maven.main.skip}</skipMain>
  <skipMultiThreadWarning default-value="false">${maven.compiler.skipMultiThreadWarning}</skipMultiThreadWarning>
  <source default-value="1.6">${maven.compiler.source}</source>
  <staleMillis default-value="0">${lastModGranularityMs}</staleMillis>
  <target default-value="1.6">${maven.compiler.target}</target>
  <useIncrementalCompilation default-value="true">${maven.compiler.useIncrementalCompilation}</useIncrementalCompilation>
  <verbose default-value="false">${maven.compiler.verbose}</verbose>
</configuration>

these are all the configurations available for 3.8.1 version of compiler plugin. Different versions have different configurations which you can find by running your code with -X after the general mvn command. Like

mvn clean install -X
mvn compiler:compile -X

and search with id or goal or plugin name This may help with other plugins too. Eclipse, intelliJ may not show all configurations as suggestions.

Prabhu
  • 11
  • 1