8

I'm using maven-antrun-plugin to execute a thrift shell command. I can compile one file per <exec> with <arg value="...path/to/file.thrift" />, but I would like to compile all .thrift files in a directory. How can I do this?

I tried using <arg value="...path/to/*.thrift" />, but Maven rejected this syntax.

apennebaker
  • 681
  • 2
  • 8
  • 17
  • 1
    Is it possible to generated python/other language files, or it can only generated java files? – Khatri Jul 16 '18 at 05:57

3 Answers3

15

The are several options to compile thrift files in maven project:

Option 1: Use maven thrift plugin (the best one)

Maven Thrift plugin supports generation of sources/test sources, recompile on modify, etc. Basically, it's the most convenient way to use thrift in Maven project.

  1. Put your sources in src/main/thrift (or src/test/thrift for test thrift sources).
  2. Install the thrift binary to /usr/local/bin/thrift (or any other place, you prefer)
  3. Add the plugin to the plugins section of your pom.xml:

        <plugin>
            <groupId>org.apache.thrift.tools</groupId>
            <artifactId>maven-thrift-plugin</artifactId>
            <version>0.1.11</version>
            <configuration>
                <thriftExecutable>/usr/local/bin/thrift</thriftExecutable>
            </configuration>
            <executions>
                <execution>
                    <id>thrift-sources</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
                <execution>
                    <id>thrift-test-sources</id>
                    <phase>generate-test-sources</phase>
                    <goals>
                        <goal>testCompile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    

That's it: next time you call mvn compile java sources will be generated from thrift. Generated sources will be placed into target/generated-sources/thrift/ directory, and this directory will be added to the compile path for java compiler.

You can find the detailed instructions, samples and more on the Github: https://github.com/dtrott/maven-thrift-plugin.

Option 2: Use Maven Antrun plugin

If it's necessary for some reason to use antrun plugin, it's better to use apply command instead of exec to process a set of files.

I'll write only a basic idea of ant target, since conditional recompilation on modification is probably out of scope of this question:

<target name="compile-thrift">
    <!-- Define fileset of thrift files -->
    <fileset id="thrift.src.files" dir="${src.thrift.dir}">
        <include name="**/*.thrift"/>
    </fileset>

    <!-- Invoke thrift binary for each of these files -->
    <apply executable="${thrift.compiler}" resultproperty="thrift.compile.result"
    failifexecutionfails="true" failonerror="true"
    searchpath="true" dir="${src.thrift.dir}">
        <arg value="-o"/>
        <arg value="${thrift.dest.dir}"/>
        <arg value="--gen"/>
        <arg value="java"/>
        <srcfile/>
        <fileset refid="thrift.src.files"/>
    </apply>
</target>

Option 3: Use antrun with exec ant task

If it's absolutely necessary for some reason to use Antrun plugin and exec task, there's a way to do so. I'd advise against it, since it's ugly and not portable, but it might work. Use xargs to invoke Thrift compiler for a list of files:

<exec dir="${src.thrift.dir}" executable="bash">
  <arg line="ls * | xargs ${thrift.compiler} -o ${thrift.dest.dir} --gen java"/>
</exec>
Peter Szanto
  • 7,568
  • 2
  • 51
  • 53
Wildfire
  • 6,358
  • 2
  • 34
  • 50
  • I'd like to Xlint my handwritten .java code, while not Xlinting my thrift-generated .java code. Could you tweak your solution to accomplish this? – apennebaker Oct 01 '13 at 16:31
  • While using maven-thrift plugin, I was getting this error:nknown option java:hashcode(thrift: 0.11.0). Does anybody else face the same issue? I searched over net, says: it doesn't have java:hashcode option anymore. Downgrading to thrift 0.9.3 worked for people. But I wanted to use this or latest version only, any suggestions? – Khatri Jul 16 '18 at 06:20
  • @Wildfire Is there way to avoid reference to **thriftExecutable** ? I want that maven downloadloads that generator on startup. https://stackoverflow.com/questions/52044010/how-to-use-thrift-generator-as-maven-dependencyhow-to-avoid-reference-to-exe-f – gstackoverflow Aug 28 '18 at 08:55
10

I'm playing aground with thrift 0.10.0 and found that in order to use maven-thrift-plugin I had to provide generator option:

        <plugin>
            <groupId>org.apache.thrift.tools</groupId>
            <artifactId>maven-thrift-plugin</artifactId>
            <version>0.1.11</version>
            <configuration>
                <thriftSourceRoot>${basedir}/src/main/resources/thrift</thriftSourceRoot>
                <generator>java</generator>
            </configuration>
            <executions>
                <execution>
                    <id>thrift-sources</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
                <execution>
                    <id>thrift-test-sources</id>
                    <phase>generate-test-sources</phase>
                    <goals>
                        <goal>testCompile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

Otherwise it would complain that "unknown option java:hashcode". In fact, seems that there's no such option in java generator any more. thrift --help gives these options:

  java (Java):
beans:           Members will be private, and setter methods will return void.
private-members: Members will be private, but setter methods will return 'this' like usual.
nocamel:         Do not use CamelCase field accessors with beans.
fullcamel:       Convert underscored_accessor_or_service_names to camelCase.
android:         Generated structures are Parcelable.
android_legacy:  Do not use java.io.IOException(throwable) (available for Android 2.3 and above).
option_type:     Wrap optional fields in an Option type.
java5:           Generate Java 1.5 compliant code (includes android_legacy flag).
reuse-objects:   Data objects will not be allocated, but existing instances will be used (read and write).
sorted_containers:
                 Use TreeSet/TreeMap instead of HashSet/HashMap as a implementation of set/map.
generated_annotations=[undated|suppress]:
                 undated: suppress the date at @Generated annotations
                 suppress: suppress @Generated annotations entirely
apadana
  • 13,456
  • 15
  • 82
  • 98
Cyrusmith
  • 747
  • 1
  • 9
  • 17
0

Is there way to avoid reference to thriftExecutable ? I want that maven downloadloads that generator on startup. (See this)

maven-thrift-plugin usually requires you to install Thrift compiler in the build server as it requires to reference its path in <thriftExecutable>.

For people who don't want to do that and if your build server is already installed with docker runtime , another option is to compile it using a docker image that is already created and shared by people such as this one. So ,

Option 4: Use Docker Image

<plugin>
    <groupId>io.fabric8</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.42.1</version>
    <configuration>
        <images>
            <image>
                <name>cspwizard/thrift:0.18.1</name>
                <run>
                    <platform>linux/amd64</platform>
                    <volumes>
                        <bind>
                            <volume>src/main/resources:/data</volume>
                            <volume>src/main/java:/out</volume>
                        </bind>
                    </volumes>
                    <cmd>--gen java -out /out -v -r /data/build.thrift</cmd>
                </run>
            </image>
        </images>
    </configuration>
    <executions>
        <execution>
            <id>start</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>start</goal>
            </goals>
        </execution>
    </executions>
</plugin>
 

This configuration assumes you put all the .thrift file in src/main/resources/data. build.thrift is the main entry file which you need to manually include all .thrift that you want to compile :

include "foo.thrift"
include "bar.thrift"
include ........

It needs to do that simply because the thrift compiler does not support specifying a list of .thrift file to be compiled. (see this for more info).

Ken Chan
  • 84,777
  • 26
  • 143
  • 172