diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5b697ff1896339c3a77d0d224b260ee4e8acf82e..d9b66d8b15bf8b08fdfc05c59c7aad821f264931 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -12,7 +12,7 @@ cache:
     - .gradle/caches
 
 build:
-  image: openjdk:11
+  image: openjdk:8
   stage: build
   script:
     - ./gradlew --console=plain --no-daemon assemble fatJar
@@ -21,7 +21,7 @@ build:
       - "/builds/jastadd/relational-rags/build/libs/relast-*.jar"
 
 test:
-  image: openjdk:11
+  image: openjdk:8
   stage: test
   script:
     - ./gradlew --console=plain --no-daemon --info test
@@ -36,13 +36,16 @@ pages:
     paths:
     - public
   only:
-  - master
+    - master
 
 publish_dev:
-  image: openjdk:11
+  image: openjdk:8
   stage: deploy
   needs:
     - test
   script:
     - "./gradlew setDevVersionForCI"
-    - "./gradlew publish"
\ No newline at end of file
+    - "./gradlew publish"
+  only:
+    - develop
+    - master
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 46997637b262d0b2c2696a43154fc008f4afa3b5..8a44f97d5c135c9262f166256036043ad49748be 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -23,33 +23,27 @@ This location can be [configured](#build-configuration).
 
 ## Build configuration
 
-Currently, the test setup is configured within `build.gradle` using a specialized Gradle task `RelastTest`.
+Currently, the test setup is configured within `build.gradle` using a specialized Gradle task `RelastTest` provided by the [preprocessor testing Gradle plugin][preprocessor-testing].
 An example configuration might look like:
 
 ```groovy
 task compileMultipleTest(type: RelastTest) {
-    relastFiles 'src/test/jastadd/multiple/Part1.relast',
-                'src/test/jastadd/multiple/Part2.relast',
-                'src/test/jastadd/multiple/Part3.relast'
-    grammarName = 'src/test/jastadd/multiple/Multiple'
-    useJastAddNames = true
-    packageName = 'multiple.ast'
-    moreInputFiles 'src/test/jastadd/Utils.jadd'
+    relast {
+        inputFiles = [file('src/test/jastadd/multiple/Part1.relast'),
+                      file('src/test/jastadd/multiple/Part2.relast'),
+                      file('src/test/jastadd/multiple/Part3.relast')]
+        grammarName = 'src/test/jastadd/multiple/Multiple'
+        useJastAddNames = true
+        noResolverHelper = true
+    }
+    jastadd {
+        packageName = 'multiple.ast'
+        inputFiles = [file('src/test/jastadd/Utils.jadd')]
+    }
 }
 ```
 
-The following options are supported, similar to the [command-line options](/../#supported-command-line-options):
-
-|        Name       |                                              Description                                               |      Required      |       Default       |
-|-------------------|--------------------------------------------------------------------------------------------------------|--------------------|---------------------|
-| `relastFiles`     | Input grammar(s). Either one or multiple files separated by comma.                                     | Yes                | _none_              |
-| `grammarName`     | Directory and file prefix for the generated grammar and jrag created by RelAST.                        | Yes                | _none_              |
-| `useJastAddNames` | Set to `true` to use accessor names for relations matching JastAdd naming convention.                  | No                 | `false`             |
-| `packageName`     | Name of the package for the Java files generated by JastAdd.                                           | Yes (not enforced) | The empty package   |
-| `moreInputFiles`  | Additional files as input for JastAdd.                                                                 | No                 | No additional files |
-| `resolverHelper`  | Set to `true` to generate means for lazy resolving.                                                    | No                 | `false`             |
-| `jastAddList`     | Alternative name for `List` nodes. Will be passed to both RelAST and JastAdd.                          | No                 | `List`              |
-| `serializer`      | Name of supported serializer. One of {`jackson`, `jackson-json-pointer`, `jackson-manual-references`}. | No                 | No serializer       |
+Please see the [documentation of the plugin][preprocessor-testing] for all options.
 
 ## Test files
 
@@ -106,3 +100,4 @@ The workflow:
 [semantic-versioning]: https://semver.org/
 [create-release]: /../-/tags/new
 [create-issue]: https://git-st.inf.tu-dresden.de/jastadd/relational-rags/issues/new
+[preprocessor-testing]: https://jastadd.pages.st.inf.tu-dresden.de/testing/
diff --git a/README.md b/README.md
index b49c377f9290f661896b992cc1d363d9334d0053..f034b04e8263eeb6065b4e30fb1da197a903219b 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 ![RelAST process](relast-process.png)
 
-See [releases page](/../../releases) for the latest version.
+See [releases page](/../../releases) for the latest version and <https://jastadd.pages.st.inf.tu-dresden.de/relational-rags/> for more documentation.
 
 The RelAST preprocessor takes a `.relast` file as input comprising AST rules and relations. It produces files that afterwards are processed by JastAdd to generated Java code.
 To use it in your project, build the JAR file running
@@ -52,21 +52,23 @@ Note that you may have to change
 
 ## Supported relations
 
-	// Directed relations
-	A.b    -> B;
-	A.b?   -> B;
-	A.bs*  -> B;
-	B      <- A.b  ;
-	B      <- A.b? ;
-	B      <- A.bs*;
+```
+// Directed relations
+A.b    -> B;
+A.b?   -> B;
+A.bs*  -> B;
+B      <- A.b  ;
+B      <- A.b? ;
+B      <- A.bs*;
 
-	// Bidirectional relations
-	A.b   <-> B.a;
-	A.b   <-> B.a?;
-	A.b   <-> B.as*;
-	A.b?  <-> B.a;
-	A.b?  <-> B.a?;
-	A.b?  <-> B.as*;
-	A.bs* <-> B.a;
-	A.bs* <-> B.a?;
-	A.bs* <-> B.as*;
+// Bidirectional relations
+A.b   <-> B.a;
+A.b   <-> B.a?;
+A.b   <-> B.as*;
+A.b?  <-> B.a;
+A.b?  <-> B.a?;
+A.b?  <-> B.as*;
+A.bs* <-> B.a;
+A.bs* <-> B.a?;
+A.bs* <-> B.as*;
+```
diff --git a/build.gradle b/build.gradle
index 188a504970f97d81e081ed8941d39699e7612103..dfa00a53260469d8d193bcc9c019d7e03ab46055 100644
--- a/build.gradle
+++ b/build.gradle
@@ -25,7 +25,7 @@ plugins {
 
 apply plugin: PreprocessorPlugin
 
-java.toolchain.languageVersion = JavaLanguageVersion.of(11)
+java.toolchain.languageVersion = JavaLanguageVersion.of(8)
 
 ext {
     mainClassName = 'org.jastadd.relast.compiler.Compiler'
@@ -63,9 +63,9 @@ idea.module.generatedSourceDirs += genSrc
 idea.module.generatedSourceDirs += testGenSrc
 
 def versionFile = 'src/main/resources/RelASTVersion.properties'
-def oldProps = new Properties()
 
 try {
+    def oldProps = new Properties()
     file(versionFile).withInputStream { stream -> oldProps.load(stream) }
     version = oldProps['version']
 } catch (ignored) {
@@ -95,9 +95,7 @@ task setDevVersionForCI() {
     }
 }
 
-jar {
-    archiveBaseName = 'relast'
-}
+jar.archiveBaseName = 'relast'
 
 task fatJar(type: Jar) {
     dependsOn jar
@@ -160,7 +158,8 @@ jastadd {
     scanner.genDir = 'src/gen/java/org/jastadd/relast/scanner'
     parser.genDir = 'src/gen/java/org/jastadd/relast/parser'
 
-    jastaddOptions = ['--lineColumnNumbers', '--safeLazy', '--visitCheck=true', '--rewrite=cnta', '--cache=all']
+    // default options are: ['--rewrite=cnta', '--safeLazy', '--visitCheck=false', '--cacheCycle=false']
+    extraJastaddOptions = ['--lineColumnNumbers', '--visitCheck=true']
 }
 
 // publish gitlab project
@@ -174,11 +173,6 @@ publishing {
     repositories {
         maven {
             url "https://git-st.inf.tu-dresden.de/api/v4/projects/$System.env.CI_PROJECT_ID/packages/maven"
-            // Uncomment the following lines to publish manually (and comment out the other credentials section)
-//            credentials(HttpHeaderCredentials) {
-//                name = "Private-Token"
-//                value = gitLabPrivateToken // the variable resides in ~/.gradle/gradle.properties
-//            }
             credentials(HttpHeaderCredentials) {
                 name = 'Job-Token'
                 value = System.getenv('CI_JOB_TOKEN')
diff --git a/gradle.properties b/gradle.properties
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/main/jastadd/backend/Serializer.jadd b/src/main/jastadd/backend/Serializer.jadd
index ac811f1598a2fd0578ae3618c2510e27190cb09a..6973c630367428d01c42410cbb74dc19b040f938 100644
--- a/src/main/jastadd/backend/Serializer.jadd
+++ b/src/main/jastadd/backend/Serializer.jadd
@@ -592,7 +592,7 @@ aspect Serializer {
     sb.append(ind(3) + "if (map.keySet().contains(unique$Id())) {\n");
     sb.append(ind(4) + "throw new RuntimeException(new SerializationException(\"UID \" + this.unique$Id() + \" is assigned to both \" + this.getClass().getSimpleName() + \":\" + this.hashCode() + \" and \" + map.get(unique$Id()).getClass().getSimpleName() + \":\" + map.get(unique$Id()).hashCode()));\n");
     sb.append(ind(3) + "} else {\n");
-    sb.append(ind(4) + "map.put(this.unique$Id, new java.lang.ref.WeakReference(this));\n");
+    sb.append(ind(4) + "map.put(this.unique$Id(), new java.lang.ref.WeakReference(this));\n");
     sb.append(ind(3) + "}\n");
     sb.append(ind(2) + "}\n");
     sb.append(ind(2) + "for (ASTNode child : astChildren()) {\n");