2

I have a maven config file that triggers autogeneration of xsd and wsdl classes as follows:

    <plugin>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-xjc-plugin</artifactId>
        <version>${cxf-xjc-plugin}</version>
        <executions>
            <execution>
                <id>generate-sources</id>
                <phase>generate-sources</phase>

                <configuration>
                    <sourceRoot>${project.build.directory}/generated/src/main/java</sourceRoot>
                    <xsdOptions>
                        //xsds, wsdls etc
                    </xsdOptions>
                </configuration>
                <goals>
                    <goal>xsdtojava</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

The generated classes go to: target/generated/src/main/java.

Problem: running 'mvn clean package' will always remove those classes. How can I prevent it? Is it possible having clean remove the full content of the target directory apart from the generated/ one?

membersound
  • 81,582
  • 193
  • 585
  • 1,120
  • Why do you want to do this? `clean` deletes the `target` directory and everything generated by Maven should go under this directory, so everything is acting like it should. The classes will get re-generated by the next build. – Tunaki Sep 25 '15 at 13:52
  • yes, but - as writte - I want to prevent the regeneration. I have some large any many wsdl files, and regeneration takes a long time. In spite, when eg moving or renaming a package, a `mvn clean` is required to the final `war` package, as otherwise the target might contain als the old compiled classes. Another case would be where a `jar` dependency is upgraded, and old ones should get deleted. In all of these cases not regenerating the wsdl java classes will save several minutes, as they are not necessairy. – membersound Sep 25 '15 at 13:55
  • 1
    So your real problem is not "how make `maven-clean-plugin` not delete `generated/`" but "how can I avoid regeneration". This is not the same question. This could be done by using a profile for example. Can you update the question accordingly? – Tunaki Sep 25 '15 at 13:59
  • *If* it's impossible to protect a folder during `clean`, then yes, this would be my question. – membersound Sep 25 '15 at 14:01
  • And in one fell swoop, [Y turned into X](http://xyproblem.info/). Nice job. :) – biziclop Sep 25 '15 at 14:05

2 Answers2

5

It is possible not to delete some directory using maven-clean-plugin but this is definitely not a good idea:

  • it goes against Maven conventions
  • it forces you to change your POM everytime you want those classes to be generated

Solution to your exact question (NOT RECOMMENDED)

You can exclude directories with the maven-clean-plugin using excludeDefaultDirectories and filesets parameters:

<plugin>
    <artifactId>maven-clean-plugin</artifactId>
    <version>2.6.1</version>
    <configuration>
        <excludeDefaultDirectories>true</excludeDefaultDirectories>
        <filesets>
            <fileset>
                <directory>${project.build.directory}</directory>
                <excludes>
                    <exclude>generated/*</exclude>
                </excludes>
            </fileset>
        </filesets>
    </configuration>
</plugin>

Note that I strongly urge you NOT to use this solution.

Proposed solution

Your actual problem is not to re-generate the classes everytime you build because it takes a lot of time. The goal is then to avoid generation by using a custom profile:

<profiles>
    <profile>
        <id>noGenerate</id>
        <properties>
            <xjc.generate>none</xjc.generate>
        </properties>
    </profile>
    <profile>
        <id>generate</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <xjc.generate>generate-sources</xjc.generate>
        </properties>
    </profile>
</profiles>

With the following plugin definition:

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-xjc-plugin</artifactId>
    <version>${cxf-xjc-plugin}</version>
    <executions>
        <execution>
            <id>generate-sources</id>
            <phase>${xjc.generate}</phase>
            <configuration>
                <sourceRoot>${project.build.directory}/generated/src/main/java</sourceRoot>
                <xsdOptions>
                    //xsds, wsdls etc
                </xsdOptions>
            </configuration>
            <goals>
                <goal>xsdtojava</goal>
            </goals>
        </execution>
    </executions>
</plugin>

It seems cxf-xjc-plugin does not have any skip parameter so we have to resort to setting the phase to none when we want to avoid execution (this is an undocumented feature but it works).

The trick is to define two profiles: one, activated by default, sets a property telling the cxf-xjc-plugin to execute in the generate-soures phase, while the other one sets a property telling the cxf-xjc-plugin not to execute.

As such, when you want to classes to be generated, you can invoke Maven with mvn clean install and when you want the classes not to be generated, you can invoke Maven with mvn clean install -PnoGenerate.

The real gain and advantage here is that you do not need to change your POM everytime you decide to generate or not the classes.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
  • Using the `excludeDefaultDirectories`, wouldn't it be possible to use `mvn gnerate-sources` to trigger explicit regeneration? – membersound Sep 25 '15 at 14:15
  • @membersound `mvn generate-sources` is always going to execute the `generate-sources` phase so the classes are going to get generated. `clean` is not invoked with `mvn generate-sources`. – Tunaki Sep 25 '15 at 14:28
2

I would have another approach.

1st) Configure your xjc plug-in to not erase any files i.e.:

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.2</version>
<executions>
    <execution>
        <goals>
            <goal>xjc</goal>
        </goals>
    </execution>
</executions>
<configuration>
    <clearOutputDir>false</clearOutputDir>
    <outputDirectory>${project.build.directory}</outputDirectory>
    <sources>
        <source>  [any xsd] </source>
    </sources>
</configuration>

2nd) Use maven-clean-plugin to clean jxc class generated dir in clean stage:

<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
<configuration>
    <filesets>
        <fileset>
            <directory>${basedir}/generated/src/main/java/...where the generated classes are</directory>
            <includes>
                <include>**/*.java</include>
            </includes>
            <followSymlinks>false</followSymlinks>
        </fileset>
    </filesets>
</configuration>

This works for me and I hope would be useful.

Francisco M
  • 163
  • 2
  • 9