For my android app I use the parceler library and the lombok library.
These are the annotations of my class:
@Table
@ToString
@Getter
@NoArgsConstructor
@Parcel
public class MyClass {
However, during gradle build, Parceler complains that there is no default empty constructor. So does this mean it doesn't recognize the @NoArgsConstructor
annotation and these two simply won't work together? Because e.g. SugarORM has no probs with it. Or am I just missing something?
This gets into how Lombok adds code to your class. Lombok uses a known trick in the Java annotation processor to add code to your class. This added code is not visible to Parceler during the annotation processor round and makes the added no-args constructor unknown to Parceler.
I'd recommend adding the no-args constructor manually, annotating the existing constructor with @ParcelConstructor
(I assume you have one) or consider using the Lombok fork Hrisey that has an @Parcelable
annotation.
We had an issue/question about this recently: https://github.com/johncarl81/parceler/issues/177
EDIT: Initial solution failed after I did some cleaning, also, it didn't work with Proguard. See updated solution below.
To solve this problem, I had to create my own custom annotation processor. The idea of this processor was to ensure processor order for the processors used by Lombok and Parceler.
Here are the steps I followed to resolve this problem:
Step 1
Create a new Java Module under the root project. Call it any name, for example parceler-lombok
, use any class name/package of your choice.
Step 2
Add lombok and Parceler annotation classes as dependency to the new module, and set source compatibility.
//File: parceler-lombok/build.gradle
apply plugin: 'java'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'org.projectlombok:lombok:1.16.16'
compile 'org.parceler:parceler:1.1.9'
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
Step 3
Create the following directory in your main source folder for the module: src/main/resources/META-INF/services
Step 4
Create a file called javax.annotation.processing.Processor
inside the directory above.
Step 5
Edit the file, and add the following lines.
lombok.launch.AnnotationProcessorHider$AnnotationProcessor
lombok.launch.AnnotationProcessorHider$ClaimingProcessor
org.parceler.ParcelAnnotationProcessor
This is a declaration of all the annotation processors available in your module. The order shows that Lombok annotation processors should be loaded before parceler's
Step 6
Now that we have our "custom annotation processor", go back to your main app module, in your build.gradle file for app, do the following:
- Remove lombok dependency (annotatorProcessor, provided or compile) directive
- Remove the parceler annotationProcessor dependency (i.e.
org.parceler:parceler
), leave the API dependency as-is. - Now add your custom annotation processor as a dependency
- Finally, ensure Java 1.7 compatibility
See snippets below :
//File: app/build.gradle
android {
//...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
//...
}
dependencies {
// ...
//Remove these ones
//provided 'org.projectlombok:lombok:1.16.16'
//annotationProcessor 'org.parceler:parceler:1.1.9'
//leave parceler API
compile 'org.parceler:parceler-api:1.1.9'
provided project(':parceler-lombok')
}
Using provided ensures that the annotation processor classes are not bundled with your app.
The following articles were very helpful:
Use @ParcelFactory on a static method building an empty object:
@Builder
public class MyClass {
@ParcelFactory
static MyClass fromParcel() {
return builder().build();
}
}
This trick can ben used with Jackson and other libraries allowing you to annotate static factory methods in addition to constructors.
来源:https://stackoverflow.com/questions/37543057/parceler-and-lombok-not-working-together