Having Maven2 copy resources to the build directory, but NOT bundle them in the JAR

17,259

Solution 1

Although the proposed solutions would work they basically work around the maven conventions. A better alternative would be to filter out the resources so they are not included in the jar but still available as resources while working in the IDE. In the pom it should look like this:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <excludes>
                            <exclude>/conf/**</exclude>
                            <exclude>/fonts/**</exclude>
                            <exclude>/images/**</exclude>
                            <exclude>/sounds/**</exclude>
                        </excludes>
                    </configuration>
                </execution>
            </executions>
        </plugin>
   </plugins>
</build>

This would effectively exclude them from the jar without any workarounds.

Here is the doc page for the jar plugin.

Though the above will answer your question may I suggest some additional possibility that could help you in your endeavour. As a second step, to still make these resources available you could package your project using the assembly plugin. this would allow you to create a zip file and place all the files, resources and jar, in an appropriate location so that when the zip is unpacked everything just falls into place.

If this project is part of a larger work you can still use the assembly plugin for each where you would have this situation and in the main project you could extract and reassemble them in a larger zip including all the necessary artifacts.

Lastly I suggest you leave the directory structure under target as-is. If you customize it it would be preferable to do it through the Maven variables so that the changes percolate to the other plugins. If you manually remove and rename stuff once Maven has gone through you may run into problems later. Normally the Maven jar plugin should be able to just get it right if you configure it the way you want so you have no needs to worry about what comes under target. Personally I use Eclipse and the pusign is pretty good at getting the IDE and Maven config in sync. For NetBeans I would suspect this would also be the case. If not the best approach would be to configure your project in NetBeans to use target/classes as a target folder for built artifacts and target/test-classes for stuff built from src/test/java.

Solution 2

Personally, I would not use the default location of resources but an "extra" location and configure the resources plugin to copy them where you want from there:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.4.3</version>
        <executions>
          <execution>
            <id>copy-resources</id>
            <!-- here the phase you need -->
            <phase>validate</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>${basedir}/target</outputDirectory>
              <resources>          
                <resource>
                  <directory>src/non-packaged-resources</directory>
                  <filtering>true</filtering>
                </resource>
              </resources>              
            </configuration>            
          </execution>
        </executions>
      </plugin>
    </plugins>
    ...
  </build>
  ...
</project>

If you insist with using the default location (src/main/resources), I think you'll have to configure some exclusions (see below) to avoid resources getting copied by default and then use the same approach as above.

Another option would be to use the AntRun maven plugin and Ant to move files but this is not really the maven way so I won't detail it.

Resources

Share:
17,259
Steve Perkins
Author by

Steve Perkins

I am a software developer working primarily in mixed Java / .NET shops, with occasional forays into Scala or Golang. Over the past several years I've been particularly focused on microservice architecture (e.g. messaging middleware and REST/HATEOAS)... and working with data at scale (e.g. Apache Cassandra, Spark, Storm, and ElasticSearch/Lucene). I am the author of 'Hibernate Search by Example', from Packt Publishing. Website/blog: http://steveperkins.com Twitter: https://twitter.com/stevedperkins GitHub: https://github.com/steve-perkins LinkedIn: http://www.linkedin.com/in/perkinssteve/

Updated on June 21, 2022

Comments

  • Steve Perkins
    Steve Perkins almost 2 years

    I've started a new Maven project in NetBeans, accepting all the defaults. The POM, with all the JAR dependencies stripped out, is cut-n-pasted at the bottom of this question.

    The application reads in various properties files (e.g. logging and config). It also reads in external resources such as fonts, images, and sounds. I do NOT want all these resources to be bundled up into the JAR file. Instead, I plan to deploy them in subdirectories beneath the directory where the JAR is deployed.

    A simplified view of the project's directory structure looks like this:

    -src
       |---main
               |---java
                       |---com.mypackage, etc
               |---resources
                            |---conf
                            |---fonts
                            |---images
                            |---sounds
    +target
    

    What I would like to have after a clean build would look like this:

    +src
    -target
           |---myproject-1.0.0.jar (compiled contents of "src/main/java" ONLY)
           |---conf
           |---fonts
           |---images
           |---sounds
    

    However, when I do a "clean-and-build" or an "exec" through NetBeans (or the command-line for that matter)... what I'm actually getting looks like this:

    +src
    -target
           |---classes
                      |---("src/main/java" and "src/main/resources" slammed together)
           |---myproject-1.0.0.jar (the "classes" subdirectory JAR'ed up)
    

    Can someone point me in the right direction for getting that first result rather than the second? I apologize if this is a silly question (I'm a Maven rookie), or if I overlooked a previously-asked duplicate. However, from the searching I've done on Stack Overflow... it looks like all the duplicate questions try to go the other way! (i.e. get resources into a JAR rather than keep them out)

    pom.xml:

    <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/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>steveperkins</groupId>
        <artifactId>myproject</artifactId>
        <packaging>jar</packaging>
        <version>1.0.0</version>
        <name>My Project</name>
        <url>http://maven.apache.org</url>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.0.2</version>
                    <configuration>
                        <source>1.4</source>
                        <target>1.4</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        <dependencies>
        ...
    
  • Devanshu Mevada
    Devanshu Mevada over 13 years
    This wouldn't give what the OP is asking for (i.e. conf, font, etc in the root of the target directory), at least not without more efforts.
  • Newtopian
    Newtopian over 13 years
    That's my point, he doe snot need to change his root folder at all. Mucking around the assumed maven conventions is the path to darkness. Maven is great so long as you play nice with it. If you try and change the world around it it will break in many unexpected places
  • Devanshu Mevada
    Devanshu Mevada over 13 years
    Which is why I suggested to use another location than src/main/resources to achieve what the OP asked for without breaking anything.
  • Steve Perkins
    Steve Perkins over 13 years
    I like this approach best because it plays nice with the "exec" goal, used by NetBeans to run the application from within the IDE. I don't really care if everything but the kitchen sink gets copied to "target/classes" during the build process... just as long as I wind up with non-Java resources outside the JAR file as a final deliverable. I can use an assembler to package everything up once the JAR is properly built.
  • Steve Perkins
    Steve Perkins over 13 years
    However, I must note that this pom example above didn't work for me as written. I ended up promoting that <configuration> element two levels, to be a direct child of the <plugin> element... and then eliminated the <executions> element altogether. Worked fine then.
  • Newtopian
    Newtopian over 13 years
    @Pascal : What exactly did my proposal break anything that yours does not ? In fact doing the filtering later in the process allows all other parts of the system to find things as it expect. Had the files been absent from the target folder the program would not find the resources in the same way it would when it is deployed unless additional configuration is brought to the build process. As I see it to use another location for resources is far more riskier with regard to breaking something than simply filtering them from entering the jar at the right time.
  • Newtopian
    Newtopian over 13 years
    @Steve : thank you for the comment, I have brought corrections to the answer to reflect your experience.
  • Devanshu Mevada
    Devanshu Mevada over 13 years
    If you try and change the world around it it will break in many unexpected places => I just responded that an additional resource location doesn't break anything. But whether we agree or not is not really important.
  • Newtopian
    Newtopian over 13 years
    agreed, agreement is not mandatory :-). My point was, in saying what you quoted here, that placing resources in a different location so that they are not picked up by maven, and as a result, placed in the target folder would prevent the application from finding these resources when executing it from the IDE. I tend to want the IDE environment and the final deployment environment as close as possible to one another. Here what I understood from the question was that these resources were expected to be found at this location just that them being inside the jar was undesirable....
  • Newtopian
    Newtopian over 13 years
    this said since Java handles all but the most basic operations differently when resources are within a jar rather than as individual files renders most of this argument moot anyway. As for my desire for counter arguments it was far more out of curiosity to explore someone else's experience and see the motivations behind your solution in the hopes of learning something new. To cleave between right and wrong is a trap easy to fall into yet it remains a trap nonetheless I try to stay away from. On this note, great many thanks for your comments and replies.