diff --git a/spec/jastadd/Backend.jadd b/spec/jastadd/Backend.jadd
index 2171c5dc13cbf785a49a40a960c13f87853985d7..bcc9c37ab7ff60f4a39664ba0d5c137cb265dd78 100644
--- a/spec/jastadd/Backend.jadd
+++ b/spec/jastadd/Backend.jadd
@@ -163,9 +163,10 @@ aspect BackendDirectedAPI {
 
 	public void ManyRelationComponent.generateDirectedAPI(StringBuilder sb) {
 		// Get
-		sb.append(ind(1) + "public Collection<" + ofTypeDecl() + "> " + toTypeDecl());
+		sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl());
 		sb.append("." + name() + "() {\n");
-		sb.append(ind(2) + "return get" + getImplAttributeName() + "();\n");
+		sb.append(ind(2) + "ArrayList<List> l = get" + getImplAttributeName() + "();\n");
+		sb.append(ind(2) + "return l != null ? l : Collections.emptyList();\n");
 		sb.append(ind(1) + "}\n");
 
 		// Add
@@ -223,7 +224,8 @@ aspect BackendBidirectionalAPI {
 			} else if (r.multiplicityOpt()) {
 
 			} else if (r.multiplicityMany()) {
-				
+				l.generateBiMany(sb);
+				r.generateBiMany(sb);
 			}
 		}
 	}
@@ -265,6 +267,49 @@ aspect BackendBidirectionalAPI {
 			sb.append(ind(1) + "}\n");
 		}
 	}
+
+	public void RelationComponent.generateBiMany(StringBuilder sb) {
+		// Get
+		sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl());
+		sb.append("." + name() + "() {\n");
+		sb.append(ind(2) + "ArrayList<" + ofTypeDecl() + "> l = get"
+			+ getImplAttributeName() + "();\n");
+		sb.append(ind(2) + "return l != null ? l : Collections.emptyList();\n");
+		sb.append(ind(1) + "}\n");
+
+		// Add
+		sb.append(ind(1) + "public void " + toTypeDecl() + ".addTo");
+		sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
+		sb.append(ind(2) + "assertNotNull(o);\n");
+		sb.append(ind(2) + "ArrayList<" + ofTypeDecl() + "> list = get" + getImplAttributeName() + "();\n");
+		sb.append(ind(2) + "if (list == null) {\n");
+		sb.append(ind(3) + "list = new ArrayList<>();\n");
+		sb.append(ind(2) + "}\n");
+		sb.append(ind(2) + "ArrayList<" + otherSide().ofTypeDecl() + "> list2 = o.get"
+			+ otherSide().getImplAttributeName() + "();\n");
+		sb.append(ind(2) + "if (list2 == null) {\n");
+		sb.append(ind(3) + "list2 = new ArrayList<>();\n");
+		sb.append(ind(2) + "}\n");
+		sb.append(ind(2) + "list.add(o);\n");
+		sb.append(ind(2) + "list2.add(this);\n");
+		sb.append(ind(2) + "set" + getImplAttributeName() + "(list);\n");
+		sb.append(ind(2) + "o.set" + otherSide().getImplAttributeName() + "(list2);\n");
+		sb.append(ind(1) + "}\n");
+
+		// Remove
+		sb.append(ind(1) + "public void " + toTypeDecl() + ".removeFrom");
+		sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
+		sb.append(ind(2) + "assertNotNull(o);\n");
+		sb.append(ind(2) + "ArrayList<" + ofTypeDecl() + "> list = get" + getImplAttributeName() + "();\n");
+		sb.append(ind(2) + "if (list != null && list.remove(o)) {\n");
+		sb.append(ind(3) + "ArrayList<" + otherSide().ofTypeDecl() + "> list2 = o.get"
+			+ otherSide().getImplAttributeName() + "();\n");
+		sb.append(ind(3) + "if (list2 != null) list2.remove(this);\n");
+		sb.append(ind(3) + "set" + getImplAttributeName() + "(list);\n");
+		sb.append(ind(3) + "o.set" + otherSide().getImplAttributeName() + "(list2);\n");
+		sb.append(ind(2) + "}\n");
+		sb.append(ind(1) + "}\n");
+	}
 }
 
 
diff --git a/test/Test.java b/test/Test.java
index 38ae7956f7e0c4828775a2754fb6698add244c8e..5a1b321240e91ddc55cc7cd40fbe449f665c5314 100644
--- a/test/Test.java
+++ b/test/Test.java
@@ -1,4 +1,5 @@
 import AST.*;
+import java.util.*;
 
 public class Test {
 	private Root r;
@@ -211,6 +212,36 @@ public class Test {
 	 * rel A.b9* <-> B.a9*;
 	 */
 	private void test9() {
+		setup();
+		a1.addToB9(b1);
+		a1.addToB9(b2);
+
+		assertEquals(a1.b9(), Arrays.asList(b1, b2));
+		assertEquals(a2.b9(), Arrays.asList());
+		assertEquals(a3.b9(), Arrays.asList());
+		assertEquals(b1.a9(), Arrays.asList(a1));
+		assertEquals(b2.a9(), Arrays.asList(a1));
+		assertEquals(b3.a9(), Arrays.asList());
+	
+		b3.addToA9(a1);
+		b3.addToA9(a3);
+		b3.addToA9(a1);
+
+		assertEquals(a1.b9(), Arrays.asList(b1, b2, b3, b3));
+		assertEquals(a2.b9(), Arrays.asList());
+		assertEquals(a3.b9(), Arrays.asList(b3));
+		assertEquals(b1.a9(), Arrays.asList(a1));
+		assertEquals(b2.a9(), Arrays.asList(a1));
+		assertEquals(b3.a9(), Arrays.asList(a1, a3, a1));
+
+		b3.removeFromA9(a1);
+
+		assertEquals(a1.b9(), Arrays.asList(b1, b2, b3));
+		assertEquals(a2.b9(), Arrays.asList());
+		assertEquals(a3.b9(), Arrays.asList(b3));
+		assertEquals(b1.a9(), Arrays.asList(a1));
+		assertEquals(b2.a9(), Arrays.asList(a1));
+		assertEquals(b3.a9(), Arrays.asList(a3, a1));
 	}
 
 
@@ -233,15 +264,17 @@ public class Test {
 	}
 
 	private void assertNull(Object obj) {
-		check(obj == null);
+		check(obj == null, "Object not null: " + obj);
 	}
 	private void assertSame(Object o1, Object o2) {
-		check(o1 == o2);
+		check(o1 == o2, "Objects not same: " + o1 + ", " + o2);
 	}
-
-	private void check(boolean b) {
+	private void assertEquals(Object o1, Object o2) {
+		check(o1.equals(o2), "Objects not equals: " + o1 + ", " + o2);
+	}
+	private void check(boolean b, String message) {
 		if (!b) {
-			throw new RuntimeException();
+			throw new RuntimeException(message);
 		}
 
 	}