How can I compile all .thrift files (*.thrift) as a Maven phase?
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.
- Put your sources in
src/main/thrift
(orsrc/test/thrift
for test thrift sources). - Install the thrift binary to /usr/local/bin/thrift (or any other place, you prefer)
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>
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