views:

13983

answers:

9

I have config files and various documents that I want to copy from the dev environment to the (dev) server directory in Maven2. Strangely, Maven does not seem strong at this task.

Options:

  1. Simple use a copy task in Maven

    <copy file="src/main/resources/config.properties" tofile="${project.server.config}/config.properties"/>

  2. Use the Ant plugin to execute copy from Ant.

  3. Construct an artifact of type zip, alongside the "main" artifact of the POM which is usually of type jar, then unpack that artifact from the repository into the target directory.

  4. maven-resources plugin, as mentioned below.

  5. Maven Assembly plugin -- but this seems to require a lot of manual definitions, when I want to do things simply and "conventionally."

  6. This page even shows how to build a plugin to do copying!

  7. maven-upload plugin, as mentioned below.

All these seem needlessly ad hoc: Maven is supposed to excel at doing these standard tasks without fuss and bother.

Any advice?

+3  A: 
Hank Gay
+3  A: 

I can only assume that your ${project.server.config} property is something custom defined and is outside of the standard directory layout.

If so, then I'd use the copy task.

whaley
Let's say I take care to put the files into the standard directory layout. Can Maven copy them to the target as-is, not in a zip/jar?
Joshua Fox
+1  A: 

Well, maven is not supposed to be good in doing fine granular tasks, it is not a scripting language like bash or ant, it is rather declarative - you say - i need a war, or an ear, and you get it. However if you need to customize how the war or ear should look like inside, you have a problem. It is just not procedural like ant, but declarative. This have some pros in the beginning, and could have a lot of cons at the end.

I guess the initial concept was to have fine plugins, that "just work" but the reality is different if you do non-standard stuff.

If you however put enough effort in your poms and few custom plugins, you'll get a much better build environment as with ant for example (depends on you project of course, but it gets more and more true for bigger projects).

siddhadev
+12  A: 

Don't shy away from the Antrun plugin. Just because some people tend to think that Ant and Maven are in opposition, they are not. Use the copy task if you need to perform some unavoidable one-off customization:

<project>
  [...]
  <build>
    <plugins>
      [...]
      <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <executions>
          <execution>
            <phase>deploy</phase>
            <configuration>
              <tasks>

                <!--
                  Place any Ant task here. You can add anything
                  you can add between <target> and </target> in a
                  build.xml.
                -->

              </tasks>
            </configuration>
            <goals>
              <goal>run</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  [...]
</project>

In answering this question, I'm focusing on the details of what you asked. How do I copy a file? The question and the variable name lead me to a larger questions like: "Is there a better way to deal with server provisioning?" Use Maven as a build system to generate deployable artifact, then perform these customizations either in separate modules or somewhere else entirely. If you shared a bit more of your build environment, there might be a better way - there are plugins to provision a number of servers. Could you attach an assembly that is unpacked in the server's root? What server are you using?

Again, I'm sure there's a better way.

tobrien
+2  A: 

Another way is to bundle these things into an artifact using the assembly plugin. Then you can use the dependency plugin to unpack these files where you want. There are also copy goals in the dependency plugin to copy artifacts.

Brian Fox
+2  A: 

The ant solution above is easiest to configure, but I have had luck using the maven-upload-plugin from Atlassian. I was unable to find good documentation, here is how I use it:

<build>
  <plugin>
    <groupId>com.atlassian.maven.plugins</groupId>
    <artifactId>maven-upload-plugin</artifactId>
    <version>1.1</version>
    <configuration>
       <resourceSrc>
             ${project.build.directory}/${project.build.finalName}.${project.packaging}
       </resourceSrc>
       <resourceDest>${jboss.deployDir}</resourceDest>
       <serverId>${jboss.host}</serverId>
       <url>${jboss.deployUrl}</url>
     </configuration>
  </plugin>
</build>

The variables like "${jboss.host}" referenced above are defined in my ~/.m2/settings.xml and are activated using maven profiles. This solution is not constrained to JBoss, this is just what I named my variables. I have a profile for dev, test, and live. So to upload my ear to a jboss instance in test environment I would execute:

mvn upload:upload -P test

Here is a snipet from settings.xml:

<server>
  <id>localhost</id>
  <username>username</username>
  <password>{Pz+6YRsDJ8dUJD7XE8=} an encrypted password. Supported since maven 2.1</password>
</server>
...
<profiles>
  <profile>
    <id>dev</id>
    <properties>
      <jboss.host>localhost</jboss.host> 
      <jboss.deployDir>/opt/jboss/server/default/deploy/</jboss.deployDir>
      <jboss.deployUrl>scp://root@localhost</jboss.deployUrl>
    </properties>
  </profile>
  <profile>
    <id>test</id>
    <properties>
       <jboss.host>testserver</jboss.host>
       ...

Notes: The Atlassian maven repo that has this plugin is here: https://maven.atlassian.com/public/

I recommend downloading the sources and looking at the documentation inside to see all the features the plugin provides.

`

Kyle Renfro
+4  A: 
<build>
    <plugins>
        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.3</version>
        </plugin>
    </plugins>
    <resources>
        <resource>
        <directory>src/main/java</directory>
            <includes>
                <include> **/*.properties</include>
            </includes>
        </resource>
    </resources>
    ...
</build>
Thanks @Peter, that was useful. I now use the resources-plugin copy-resources goal instead of antrun. The latter is actually much simpler and intuitive to define, but I couldn't get it (version 1.3) to pass all Maven custom properties (defined in <properties> section) to antrun, so I switched to resources-plugin.
Cornel Masson
+1  A: 

To summarize some of the fine answers above: Maven is designed to build modules and copy the results to a Maven repository. Any copying of modules to a deployment/installer-input directory must be done outside the context of Maven's core functionality, e.g. with the Ant/Maven copy command.

Joshua Fox
A: 

I was looking for and answer to the same question, and was able to piece together a number of different sources for this answer:

...
<repository>
    <id>atlassian</id>
    <name>Atlassian Repo</name>
    <url>https://maven.atlassian.com/content/repositories/atlassian-public&lt;/url&gt;
</repository>
...
<dependency>
    <groupId>com.atlassian.maven.plugins</groupId>
    <artifactId>maven-upload-plugin</artifactId>
    <version>1.1</version>
</dependency>
...
<plugin>
    <groupId>com.atlassian.maven.plugins</groupId>
    <artifactId>maven-upload-plugin</artifactId>
    <version>1.1</version>
    <configuration>
        <serverId>jira-repo</serverId>
        <resourceSrc>
            ${project.build.directory}/${project.build.finalName}.${project.packaging}
        </resourceSrc>
        <resourceDest>opt/jira/webapps</resourceDest> <!-- note: no leading slash -->
        <url>scp://root@jira</url>
    </configuration>
</plugin>
...

From ~/.ms/settings.xml

...
<servers>
  <server>
    <id>jira-repo</id>
    <username>myusername</username>
    <password>mypassword</password>
  </server>
</servers>
...

Then run the command: (the -X is for debug)

mvn -X upload:upload

Brett Dutton