Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven include file contents from one module in another

I have a maven application that looks like this

application_name/
    module1
        src/main/resources
            file_snippet.xml
    module2
        src/main/resources
            file_snippet.xml
    module3
        src/main/resources
            file.xml

file.xml should be like this

<workflow>
  <action>
  <%= module1/src/main/resources/file_snippet.xml %>
  </action>

  <action>
  <%= module2/src/main/resources/file_snippet.xml %>
  </action>

</workflow>

I want to include the contents of file_snippet.xml from module2 and module2 into file.xml of module3 before the build. Is that possible in maven? Is there some sort of templating language or plugin I can use?

like image 847
Royce Avatar asked Aug 16 '10 18:08

Royce


3 Answers

This is not easy, there are two parts you need to implement.

  1. get the snippets from the other module
  2. assemble the xml file using the include

for 1. you can use the dependency:unpack mojo:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <executions>
        <execution>
          <id>unpack</id>
          <phase>initialize</phase>
          <goals>
            <goal>unpack</goal>
          </goals>
          <configuration>
            <outputDirectory>${project.build.directory}/snippets</outputDirectory>
            <includes>snippets/*.xml</includes>
            <artifactItems>
              <artifactItem>
                <groupId>your.app</groupId>
                <artifactId>module1</artifactId>
                <version>${project.version}</version>
                <type>jar</type>
              </artifactItem>
              <artifactItem>
                <groupId>your.app</groupId>
                <artifactId>module2</artifactId>
                <version>${project.version}</version>
                <type>jar</type>
              </artifactItem>
            </artifactItems>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Now you have copied all snippets from module1.jar/snippets and module2.jar/snippets to target/snippets (this was the easier part).

For 2. you need to pick a template engine and create a main class to assemble your template with it, probably using the exec:java mojo something like this:

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.1</version>
    <executions>
      <execution>
        <goals>
          <goal>java</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <mainClass>com.yourcompany.YourTemplateParser</mainClass>
      <arguments>
        <argument>path/to/your/template</argument>
        <argument>path/to/the/snippets/folder</argument>
        <argument>target/path</argument>
      </arguments>
    </configuration>
  </plugin>

(Personally, I tend to use GMaven instead of exec:java, as you can write inline groovy scripts without creating custom java classes)

like image 151
Sean Patrick Floyd Avatar answered Nov 10 '22 14:11

Sean Patrick Floyd


I would like to know about some template engine for maven too, but maybe you don't need maven at first for that.

There is a way to include another xml file in a xml file : http://bobcat.webappcabaret.net/javachina/faq/xml_01.htm#dtd_Q408

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
    <!ENTITY xmlfrag SYSTEM "xmlfrag.txt" >

    <!ELEMENT root (tag1, tag2) >   
    <!ELEMENT tag1 (childtag) >
    <!ELEMENT tag2 (childtag) >
    <!ELEMENT childtag (#PCDATA) >
    <!ATTLIST childtag att NMTOKEN #REQUIRED >
]>
<root>
  &xmlfrag;
</root>

xmlfrag.txt(well formed xml fragment without xml decl)

<tag1>
  <childtag att="child1">text1</childtag>
</tag1>
<tag2>
  <childtag att="child2">text2</childtag>
</tag2>

else, for merging xml resources between dependencies/modules in maven, you can use maven-shade-plugin (with the resource transformer).

In your case :

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>1.4</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
                  <resource>file.xml</resource>
                  <!-- Add this to enable loading of DTDs
                  <ignoreDtd>false</ignoreDtd>
                  -->
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

to merge module1/src/main/resources/file.xml and module2/src/main/resources/file.xml (depending on dependencies) in module3/src/main/resources/file.xml.

like image 42
jwinandy Avatar answered Nov 10 '22 16:11

jwinandy


Quite an old post - but solution may still be useful in other contexts.

You can use maven-velocity-plugin in module3/pom.xml.

This will trigger velocity template expansion in the generate-sources phase.

<build>
        <plugins>
            <plugin>
                <groupId>com.github.vdubus</groupId>
                <artifactId>velocity-maven-plugin</artifactId>
                <version>1.1.3</version>
                <executions>
                    <execution>
                        <id>Generate source velocity</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>velocity</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}</outputDirectory>
                            <removeExtension>.vm</removeExtension>
                            <templateFiles>
                                <directory>${project.basedir}/..</directory>
                                <includes>
                                    <include>**/*.vm</include>
                                </includes>
                            </templateFiles>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
   </plugins>
</build>

module3/src/main/resources/file.xml.vm :

<workflow>
  <action>
  #include("module1/src/main/resources/file_snippet.xml")
  </action>

  <action>
  #include("module2/src/main/resources/file_snippet.xml")
  </action>

</workflow>

Note that velocity requires that all files must be under the same TEMPLATE_ROOT directory.

If included files must transitively include other files, this can be achieved by using "#parse", and processing all files with velocity ( eg rename them to FILE.xml.vm )

References

  • https://velocity.apache.org/engine/1.7/user-guide.html#include
  • https://github.com/vdubus/velocity-maven-plugin
  • solution for same problem for avro schema aggregation : https://github.com/vgheo/kafka-avro-schema-aggregation/tree/master/example-avro-agg-build
like image 28
Vlad Gheorghe Avatar answered Nov 10 '22 14:11

Vlad Gheorghe