Build my app that uses Realm with OkBuck.
Build and runs normally as if I had built with Gradle.
The build and APK are successfully generated, but when I run the app an error is raised, forcing close the app. If I build the same dependencies with Gradle, not using OkBuck, it runs perfectly. Logcat:
E/AndroidRuntime( 3447): FATAL EXCEPTION: main
E/AndroidRuntime( 3447): Process: mobile.nonaka.com.nonakaapp.ci, PID: 3447
E/AndroidRuntime( 3447): java.lang.ExceptionInInitializerError: RealmTransformer doesn't seem to be applied. Please update the project configuration to use the Realm Gradle plugin. See https://realm.io/news/android-installation-change/
E/AndroidRuntime( 3447): at io.realm.RealmConfiguration.<clinit>(RealmConfiguration.java:77)
E/AndroidRuntime( 3447): at io.realm.RealmConfiguration$Builder.initializeBuilder(RealmConfiguration.java:428)
E/AndroidRuntime( 3447): at io.realm.RealmConfiguration$Builder.<init>(RealmConfiguration.java:391)
E/AndroidRuntime( 3447): at mobile.nonaka.com.nonakaapp.NONAKAApplication.onCreate(NONAKAApplication.java:44)
E/AndroidRuntime( 3447): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1007)
E/AndroidRuntime( 3447): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4344)
E/AndroidRuntime( 3447): at android.app.ActivityThread.access$1500(ActivityThread.java:135)
E/AndroidRuntime( 3447): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
E/AndroidRuntime( 3447): at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime( 3447): at android.os.Looper.loop(Looper.java:136)
E/AndroidRuntime( 3447): at android.app.ActivityThread.main(ActivityThread.java:5017)
E/AndroidRuntime( 3447): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 3447): at java.lang.reflect.Method.invoke(Method.java:515)
E/AndroidRuntime( 3447): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
E/AndroidRuntime( 3447): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
E/AndroidRuntime( 3447): at dalvik.system.NativeStart.main(Native Method)
https://realm.io/news/android-installation-change did not help.
Build any app with Realm with OkBuck and run it.
NONAKAApplication.java line 44 has this code:
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this)
.schemaVersion(1)
.encryptionKey(realmKeyProvider.getRealmKey())
.deleteRealmIfMigrationNeeded()
.build();
This is my Gradle configuration that I used to generate the Buck files:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "io.realm:realm-gradle-plugin:2.2.1"
}
}
apply plugin: 'realm-android'
Realm version(s): 2.2.1
Realm sync feature enabled: no
Android Studio version: 2.2.3
Which Android version and device: Any device
minSdkVersion 18
targetSdkVersion 25
compileSdkVersion 25
buildToolsVersion '25.0.2'
OkBuck: 0.13.1
Gradle: 3.2
Android Gradle Plugin: 2.2.3
Thanks a lot.
That's because OkBuck doesn't support the Transform API yet.

@Zhuinden didn't notice that. Thanks a lot! Does anyone know though if it is possible to use Realm without this Transform API (maybe a older version of Realm)?
The last Realm that does not use the Realm-Transformer and the Transform API is compile "io.realm:realm-android:0.87.5"
In that version of Realm, RealmObjects cannot have custom methods, and custom logic in getters/setters.
Also, RealmResults are live in transactions, so you need to reverse iterate them instead of using for(Blah blah: blahs).
@Zhuinden thanks man. It helped me a lot!
Transform api support is actually available in okbuck, but it is not documented yet. It's a bit of work to setup right now, so we are working to make it more plug and play and will document it fully at that point.
Thanks for the info @kageiit 馃憤
Just for future reference:
https://github.com/uber/okbuck/issues/305
Question for Realm maintainers. The way transforms work in buck is that they do not have access to the gradle project model as they are run like commandline applications. This would require the RealTransformer to provide an alternate constructor that can accept a config file as an input for various configuration options instead of relying on the gradle plugin extension. Would like your thoughts on the matter
Given the above, and that support for Transformers have been merged in OkBuck I'm re-opening this as a feature request for adding support for OkBuck. We would have to look more closely at how specifically the config file looks like, but just browsing our RealmTransformer we only use two things from the Gradle project:
1) We have a custom realm closure with a setting syncEnabled. I don't know how OkBuck handles custom configuration closures, but we would have to migrate that anyway.
2) We access project.android.bootClasspath to acquire a reference to the android.jar. This would have to be provided by Buck somehow I think.
@zaki50 Do you have any input to this?
okbuck takes care of passing in the android bootclasspath as a java system property.
The syncEnabled setting can be in the config file.
Okbuck transform CLI can create a transform in two ways.
java.io.File argument constructorThe file can contain anything in it. In Realm's case it can be a simple config file like
realm.config
realm.syncEnabled=true
The transform can then read the file and parse it in whichever format it wants it in.
I also noticed that the extension is the only reason the transform relies on the gradle api. If it were possible to specify the configuration through a simple file, that dependency can be completely removed and the transform can be a 100% pure java project then. The configuration file can be created on the fly by the plugin and passed to the registerTransform() call without breaking existing users.
@cmelchior I feel supporting OkBuck is not so difficult, I'm not familiar with it.
I'll spend a bit of my time more to investigate OkBuck.
I wrote another transformer (RealmTransformerOkBuck) whose constructor accepted a File parameter.
I didn't test it at all, but is it what you mean?
// diff was removed
I would assume we could re-use the same transformer class and just keep the differences in the constructors? In our case it is just two variables, so should be doable?
@cmelchior Ah, yes.
I've updated the diff
diff --git a/gradle-plugin/src/main/groovy/io/realm/gradle/Realm.groovy b/gradle-plugin/src/main/groovy/io/realm/gradle/Realm.groovy
index 43bf3f89c..bf932bf30 100644
--- a/gradle-plugin/src/main/groovy/io/realm/gradle/Realm.groovy
+++ b/gradle-plugin/src/main/groovy/io/realm/gradle/Realm.groovy
@@ -54,7 +54,13 @@ class Realm implements Plugin<Project> {
usesAptPlugin = true
}
- project.android.registerTransform(new RealmTransformer(project))
+ def syncEnabled = project?.realm?.syncEnabled != null && project.realm.syncEnabled
+ def bootClassPathList = new ArrayList<String>()
+ project.android.bootClasspath.each {
+ bootClassPathList.add(it.absolutePath)
+ }
+
+ project.android.registerTransform(new RealmTransformer(syncEnabled, bootClassPathList))
project.repositories.add(project.getRepositories().jcenter())
project.dependencies.add("compile", "io.realm:realm-annotations:${Version.VERSION}")
diff --git a/realm-transformer/src/main/groovy/io/realm/transformer/RealmTransformer.groovy b/realm-transformer/src/main/groovy/io/realm/transformer/RealmTransformer.groovy
index e6e481355..cf03de5d6 100644
--- a/realm-transformer/src/main/groovy/io/realm/transformer/RealmTransformer.groovy
+++ b/realm-transformer/src/main/groovy/io/realm/transformer/RealmTransformer.groovy
@@ -26,8 +26,6 @@ import io.realm.annotations.Ignore
import io.realm.annotations.RealmClass
import javassist.ClassPool
import javassist.CtClass
-import javassist.LoaderClassPath
-import org.gradle.api.Project
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@@ -44,12 +42,36 @@ import static com.android.build.api.transform.QualifiedContent.*
class RealmTransformer extends Transform {
private Logger logger = LoggerFactory.getLogger('realm-logger')
- private Project project
+ private boolean syncEnabled;
+ private List<String> bootClassPathList;
- public RealmTransformer(Project project) {
- this.project = project
+ public RealmTransformer(boolean syncEnabled, List<String> bootClassPathList) {
+ this.syncEnabled = syncEnabled
+ this.bootClassPathList = bootClassPathList
}
+ // constructor for OkBuck
+ public RealmTransformer(File configFile) {
+ if (!propertiesFile.exists()) {
+ throw new FileNotFoundException(configFile.absolutePath)
+ }
+ Properties properties = new Properties()
+ configFile.withInputStream {
+ properties.load(it)
+ }
+ syncEnabled = Boolean.valueOf(properties.getProperty("realm.syncEnabled", "false"))
+ def bootClassPath = properties.getProperty("realm.bootClassPath")
+ if (bootClassPath == null || bootClassPath.empty) {
+ throw new Exception("realm.bootClassPath is not set in the configuration file.")
+ }
+
+ bootClassPathList = new ArrayList<>()
+ bootClassPath.split(',').each {
+ bootClassPathList.add(it.trim())
+ }
+ }
+
+
@Override
String getName() {
return "RealmTransformer"
@@ -177,8 +199,7 @@ class RealmTransformer extends Transform {
def env = System.getenv()
def disableAnalytics = env["REALM_DISABLE_ANALYTICS"]
if (disableAnalytics == null || disableAnalytics != "true") {
- boolean sync = project?.realm?.syncEnabled != null && project.realm.syncEnabled
- def analytics = new RealmAnalytics(packages as Set, containsKotlin, sync)
+ def analytics = new RealmAnalytics(packages as Set, containsKotlin, this.syncEnabled)
analytics.execute()
}
}
@@ -291,8 +312,8 @@ class RealmTransformer extends Transform {
// See https://code.google.com/p/android/issues/detail?id=209426
private void addBootClassesToClassPool(ClassPool classPool) {
try {
- project.android.bootClasspath.each {
- String path = it.absolutePath
+ this.bootClassPathList.each {
+ String path = it
logger.debug "Add boot class " + path + " to class pool."
classPool.appendClassPath(path)
}
diff --git a/realm/realm-library/build.gradle b/realm/realm-library/build.gradle
index ac7f1affb..94f4be798 100644
--- a/realm/realm-library/build.gradle
+++ b/realm/realm-library/build.gradle
@@ -117,7 +117,12 @@ coveralls.jacocoReportPath = "${buildDir}/reports/coverage/debug/report.xml"
import io.realm.transformer.RealmTransformer
-android.registerTransform(new RealmTransformer())
+def syncEnabled = false
+def bootClassPathList = new ArrayList<String>()
+project.android.bootClasspath.each {
+ bootClassPathList.add(it.absolutePath)
+}
+android.registerTransform(new RealmTransformer(syncEnabled, bootClassPathList))
repositories {
maven { url "https://jitpack.io" }
@kageiit How can I test transformer-enabled OkBuck?
And currently I wrote a code to get boot class path from the configuration file.
Which system property should we use for bootclasspath?
@zaki50 the android bootclasspath is already passed in the transform invocation as a referenced input jar.
To test it just add to your root build.gradle:
okBuck {
...
experimental {
transform = true
}
transform {
transforms = [
'APP-FLAVOUR' : [
[transform : "FULL_QUALIFIED_CLASS_NAME",
configFile: "CONFIG_FILE_PATH"]
],
]
}
}
dependencies {
transform REALM_DEPENDENCY
}
I also just cut and released v0.17.0 of okbuck that has support for the transforms baked in. You can use the configuration snippet @malbano posted above to test it out.
More details in the release notes: https://github.com/uber/okbuck/releases/tag/v0.17.0
@kageiit @malbano Thanks. I'll test my code and make a PR for this.
I've got some errors.
+ java -Dokbuck.inJarsDir=/Users/zaki/fromgit/realm/realm_template/buck-out/bin/app/java_classes_preprocess_in_bin_debug -Dokbuck.outJarsDir=/Users/zaki/fromgit/realm/realm_template/buck-out/bin/app/java_classes_preprocess_out_bin_debug -Dokbuck.androidBootClasspath=/usr/local/Cellar/android-sdk/24.4.1_1/platforms/android-24/android.jar:/usr/local/Cellar/android-sdk/24.4.1_1/platforms/android-24/optional/org.apache.http.legacy.jar -Dokbuck.configFile=/Users/zaki/fromgit/realm/realm_template/buck-out/gen/.okbuck/cache/transform/realm.config -Dokbuck.transformClass=io.realm.transformer.RealmTransformer -cp /Users/zaki/fromgit/realm/realm_template/buck-out/gen/.okbuck/cache/transform/okbuck_transform.jar com.uber.okbuck.transform.CliTransform
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8 -Dgroovy.source.encoding=UTF-8
java.io.IOException: Stream closed
at java.io.BufferedInputStream.getInIfOpen(BufferedInputStream.java:159)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:337)
at java.io.DataInputStream.readUTF(DataInputStream.java:589)
at java.io.DataInputStream.readUTF(DataInputStream.java:564)
at org.codehaus.groovy.reflection.GeneratedMetaMethod$DgmMethodRecord.loadDgmInfo(GeneratedMetaMethod.java:177)
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.registerMethods(MetaClassRegistryImpl.java:186)
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.<init>(MetaClassRegistryImpl.java:96)
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.<init>(MetaClassRegistryImpl.java:74)
at groovy.lang.GroovySystem.<clinit>(GroovySystem.java:36)
at org.codehaus.groovy.runtime.InvokerHelper.<clinit>(InvokerHelper.java:65)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallStaticSite(CallSiteArray.java:75)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallSite(CallSiteArray.java:162)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at io.realm.transformer.RealmTransformer.<init>(RealmTransformer.groovy:44)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.uber.okbuck.transform.TransformRunner.runTransform(TransformRunner.java:74)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:96)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:51)
Exception in thread "main" java.lang.RuntimeException: groovy.lang.MissingMethodException: No signature of method: java.util.LinkedList.each() is applicable for argument types: (io.realm.transformer.RealmTransformer$_getClassNames_closure16) values: [io.realm.transformer.RealmTransformer$_getClassNames_closure16@2a17b7b6]
Possible solutions: wait(), wait(long), add(java.lang.Object), add(java.lang.Object), add(java.lang.Object), push(java.lang.Object)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:98)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:51)
Caused by: groovy.lang.MissingMethodException: No signature of method: java.util.LinkedList.each() is applicable for argument types: (io.realm.transformer.RealmTransformer$_getClassNames_closure16) values: [io.realm.transformer.RealmTransformer$_getClassNames_closure16@2a17b7b6]
Possible solutions: wait(), wait(long), add(java.lang.Object), add(java.lang.Object), add(java.lang.Object), push(java.lang.Object)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:49)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at io.realm.transformer.RealmTransformer.getClassNames(RealmTransformer.groovy:247)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite$StaticMetaMethodSiteNoUnwrapNoCoerce.invoke(StaticMetaMethodSite.java:151)
at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.callStatic(StaticMetaMethodSite.java:102)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:56)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:194)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:206)
at io.realm.transformer.RealmTransformer.transform(RealmTransformer.groovy:110)
at com.android.build.api.transform.Transform.transform(Transform.java:308)
at com.uber.okbuck.transform.TransformRunner.runTransform(TransformRunner.java:104)
at com.uber.okbuck.transform.TransformRunner.runTransform(TransformRunner.java:80)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:96)
... 1 more
BUILD FAILED: //app:bin_debug failed with exit code 1:
genrule
stderr: + java -Dokbuck.inJarsDir=/Users/zaki/fromgit/realm/realm_template/buck-out/bin/app/java_classes_preprocess_in_bin_debug -Dokbuck.outJarsDir=/Users/zaki/fromgit/realm/realm_template/buck-out/bin/app/java_classes_preprocess_out_bin_debug -Dokbuck.androidBootClasspath=/usr/local/Cellar/android-sdk/24.4.1_1/platforms/android-24/android.jar:/usr/local/Cellar/android-sdk/24.4.1_1/platforms/android-24/optional/org.apache.http.legacy.jar -Dokbuck.configFile=/Users/zaki/fromgit/realm/realm_template/buck-out/gen/.okbuck/cache/transform/realm.config -Dokbuck.transformClass=io.realm.transformer.RealmTransformer -cp /Users/zaki/fromgit/realm/realm_template/buck-out/gen/.okbuck/cache/transform/okbuck_transform.jar com.uber.okbuck.transform.CliTransform
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8 -Dgroovy.source.encoding=UTF-8
java.io.IOException: Stream closed
at java.io.BufferedInputStream.getInIfOpen(BufferedInputStream.java:159)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:337)
at java.io.DataInputStream.readUTF(DataInputStream.java:589)
at java.io.DataInputStream.readUTF(DataInputStream.java:564)
at org.codehaus.groovy.reflection.GeneratedMetaMethod$DgmMethodRecord.loadDgmInfo(GeneratedMetaMethod.java:177)
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.registerMethods(MetaClassRegistryImpl.java:186)
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.<init>(MetaClassRegistryImpl.java:96)
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.<init>(MetaClassRegistryImpl.java:74)
at groovy.lang.GroovySystem.<clinit>(GroovySystem.java:36)
at org.codehaus.groovy.runtime.InvokerHelper.<clinit>(InvokerHelper.java:65)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallStaticSite(CallSiteArray.java:75)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallSite(CallSiteArray.java:162)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at io.realm.transformer.RealmTransformer.<init>(RealmTransformer.groovy:44)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.uber.okbuck.transform.TransformRunner.runTransform(TransformRunner.java:74)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:96)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:51)
Exception in thread "main" java.lang.RuntimeException: groovy.lang.MissingMethodException: No signature of method: java.util.LinkedList.each() is applicable for argument types: (io.realm.transformer.RealmTransformer$_getClassNames_closure16) values: [io.realm.transformer.RealmTransformer$_getClassNames_closure16@2a17b7b6]
Possible solutions: wait(), wait(long), add(java.lang.Object), add(java.lang.Object), add(java.lang.Object), push(java.lang.Object)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:98)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:51)
Caused by: groovy.lang.MissingMethodException: No signature of method: java.util.LinkedList.each() is applicable for argument types: (io.realm.transformer.RealmTransformer$_getClassNames_closure16) values: [io.realm.transformer.RealmTransformer$_getClassNames_closure16@2a17b7b6]
Possible solutions: wait(), wait(long), add(java.lang.Object), add(java.lang.Object), add(java.lang.Object), push(java.lang.Object)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:49)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at io.realm.transformer.RealmTransformer.getClassNames(RealmTransformer.groovy:247)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite$StaticMetaMethodSiteNoUnwrapNoCoerce.invoke(StaticMetaMethodSite.java:151)
at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.callStatic(StaticMetaMethodSite.java:102)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:56)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:194)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:206)
at io.realm.transformer.RealmTransformer.transform(RealmTransformer.groovy:110)
at com.android.build.api.transform.Transform.transform(Transform.java:308)
at com.uber.okbuck.transform.TransformRunner.runTransform(TransformRunner.java:104)
at com.uber.okbuck.transform.TransformRunner.runTransform(TransformRunner.java:80)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:96)
... 1 more
One is java.io.IOException: Stream closed at the line private Logger logger = LoggerFactory.getLogger('realm-logger') in RealmTransformer.groovy
Another is groovy.lang.MissingMethodException: No signature of method: java.util.LinkedList.each() at https://github.com/realm/realm-java/blob/v2.3.0/realm-transformer/src/main/groovy/io/realm/transformer/RealmTransformer.groovy#L227
We are expecting groovy's list, but actual instance from CliTransform seems an instance of java.util.LinkedList.
@kageiit What do you think? Can you fix it in OkBuck?
@zaki50 It's easier to review if you just push a Pull Request and mark it as "In Progress" 馃槃
@zaki50 I think the problem lies here: https://github.com/realm/realm-java/blob/master/realm-transformer/build.gradle#L50
the gradleApi() and localGroovy() declarations basically do not get packaged into the pom of the transform becuase they are expected to be provided by the upstream project's gradle installation
so when you do
dependencies {
transform 'realm-transform'
}
Okbuck will pull in real-transform and its pom dependencies to make a fat jar that can be run via the transform-cli in buck. Since buck itself does not have a groovy installation, that needs to be packaged into the fat jar as well, so there are a couple of options
dependencies {
transform 'real-transform'
transform localGroovy()
transform gradleApi()
}
realm-transformer a pure java project and remove dependencies on groovy and gradle api completely. I think with #4133 the gradleAPi() dpenednecy is no longer required as you have a provider interface. You really only need the groovy dependencyThanks @kageiit
I tried the first option last week but no success (IIRC). I'll confirm that later.
I'd like to avoid the second option. We are using groovy methods in many places...
I think import groovy.io.FileType is the only actual groovy-specific thing.
I'm sure this could be rewritten to Java without too much trouble.
Hmm...
Do you think adding the incremental support could have also solved this one?
There is only one groovy file left - https://github.com/realm/realm-java/blob/539054e7923f7efda693733344a5cf436d377b0e/realm-transformer/src/main/groovy/io/realm/transformer/GroovyUtil.groovy
If this is moved over, then there is no reliance on groovy types and it could enable okbuck support
Opened https://github.com/realm/realm-java/pull/6025 to address the move
I'm getting the same error with the following okbuck configuration:
okBuck {
...
experimental {
transform = true
}
transform {
transforms = [
'debug' : [
[transform : "io.realm.transformer.RealmTransformer",
],
]
}
}
dependencies {
transform "io.realm:realm-gradle-plugin:5.3.1"
}
Is there something I'm missing?
@jtrouvere you need to try with 5.4.0-SNAPSHOT
And you also need to run it for release if that's a thing
I still get the error even though i use 5.5.0-SNAPSHOT ..
Hmmm, how can i setup realm transformer on my project ?
Is there any instruction to do that ? I've tried @jtrouvere solution, but app still crashing ..
Thank you
Theoretically, 5.4.0 is supposed to work with OkBuck.
If something is failing, you need to be specific about the actual crash and stuff.
@Zhuinden okay, i got this error ..
java.lang.ExceptionInInitializerError: RealmTransformer doesn't seem to be applied. Please update the project configuration to use the Realm Gradle plugin. See https://realm.io/news/android-installation-change/
at io.realm.RealmConfiguration.<clinit>(RealmConfiguration.java:80)
at io.realm.RealmConfiguration$Builder.initializeBuilder(RealmConfiguration.java:501)
at io.realm.RealmConfiguration$Builder.<init>(RealmConfiguration.java:487)
at io.realm.Realm.init(Realm.java:273)
at id.xcromez.what2watch.What2Watch.onCreate(What2Watch.java:23)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1012)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4553)
at android.app.ActivityThread.access$1500(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1364)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
And the crash come from this file What2Watch.java:23 which is Realm.init(this); :
@Override
public void onCreate() {
super.onCreate();
if (!BuildConfig.DEBUG) {
Fabric.with(this, new Crashlytics());
}
Realm.init(this);
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().deleteRealmIfMigrationNeeded().build();
Realm.setDefaultConfiguration(realmConfiguration);
}
And i put this on my build.gradle :
okbuck {
buildToolVersion = "27.0.3"
target = "android-26"
buckBinary = "com.github.facebook:buck:v2018.07.23.01@pex"
lint {
disabled = true
}
experimental {
transform = true
}
transform {
transforms = [
'debug': [
[transform: "io.realm.transformer.RealmTransformer",
],
]
]
}
}
Is there something that i missed ?
Thanks ..
@aldochristiaan any chance you have a small repro project that you can put on github? Will help diagnose the issue faster
@kageiit i don't have it at this moment, but i'll try to create one and come back here later ..
Have you tried with
transform {
transforms = [
'appDebug' : [
[transform : "io.realm.transformer.RealmTransformer"]
],
'appRelease' : [
[transform : "io.realm.transformer.RealmTransformer"]
]
]
}
experimental {
transform = true
}
}
dependencies {
transform "io.realm:realm-transformer:5.4.0"
}
@Zhuinden i got this error :
Input jars dir: /Users/bukalapak/Documents/Aldo/What2Watch/buck-out/bin/app/bin_debug#class_file_to_dex_processing/non_predexed_root/bin/java_classes_preprocess_in
Output jars dir: /Users/bukalapak/Documents/Aldo/What2Watch/buck-out/bin/app/bin_debug#class_file_to_dex_processing/non_predexed_root/bin/java_classes_preprocess_out
Exception in thread "main" java.lang.NoClassDefFoundError: org/gradle/api/Project
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
at java.lang.Class.getConstructor0(Class.java:3075)
at java.lang.Class.newInstance(Class.java:412)
at com.uber.okbuck.transform.TransformRunner.runTransform(TransformRunner.java:75)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:96)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:51)
Caused by: java.lang.ClassNotFoundException: org.gradle.api.Project
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
Build failed: Command failed with exit code 1.
stderr: Exception in thread "main" java.lang.NoClassDefFoundError: org/gradle/api/Project
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
at java.lang.Class.getConstructor0(Class.java:3075)
at java.lang.Class.newInstance(Class.java:412)
at com.uber.okbuck.transform.TransformRunner.runTransform(TransformRunner.java:75)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:96)
at com.uber.okbuck.transform.CliTransform.main(CliTransform.java:51)
Caused by: java.lang.ClassNotFoundException: org.gradle.api.Project
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
When running <genrule>.
When building rule //app:bin_debug#class_file_to_dex_processing.
Here is my build.gradle file:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
google()
mavenCentral()
maven {
url 'https://maven.fabric.io/public'
}
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.3'
classpath 'io.fabric.tools:gradle:1.+'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.51'
classpath 'com.jakewharton:butterknife-gradle-plugin:9.0.0-SNAPSHOT'
classpath 'com.uber:okbuck:0.40.0'
classpath 'io.realm:realm-gradle-plugin:5.4.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
google()
maven {
url 'https://maven.fabric.io/public'
}
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
}
apply plugin: 'com.uber.okbuck'
okbuck {
buildToolVersion = "27.0.3"
target = "android-26"
// buckBinary = "com.github.facebook:buck:v2018.07.23.01@pex"
lint {
disabled = true
}
transform {
transforms = [
'appDebug' : [
[transform : "io.realm.transformer.RealmTransformer"]
],
'appRelease' : [
[transform : "io.realm.transformer.RealmTransformer"]
]
]
}
experimental {
transform = true
}
}
dependencies {
transform 'io.realm:realm-transformer:5.4.0'
}
task clean(type: Delete) {
delete rootProject.buildDir
}
ext {
// Sdk and tools
minSdkVersion = 19
targetSdkVersion = 26
compileSdkVersion = 26
buildToolsVersion = '27.0.3'
// App dependencies
supportLibraryVersion = '27.1.1'
constraintLayoutVersion = '1.1.2'
guavaVersion = '18.0'
junitVersion = '4.12'
mockitoVersion = '1.10.19'
powerMockito = '1.6.2'
hamcrestVersion = '1.3'
runnerVersion = '1.0.0'
rulesVersion = '1.0.0'
espressoVersion = '3.0.1'
rxjavaVersion = '2.1.3'
rxandroidVersion = '2.0.1'
multiDexVersion = '1.0.2'
}
@aldochristiaan In a way, that is much more interesting, because now it tries to apply the transform, but I don't know why it fails.
What is your Gradle version?
@Zhuinden i tried gradle version 4.6 , 4.7, 4.9 but it didn't work :(
The build succeed tho 馃槄
Most helpful comment
okbuck takes care of passing in the android bootclasspath as a java system property.
The syncEnabled setting can be in the config file.
Okbuck transform CLI can create a transform in two ways.
java.io.Fileargument constructorThe file can contain anything in it. In Realm's case it can be a simple config file like
realm.configThe transform can then read the file and parse it in whichever format it wants it in.