diff --git a/spec/jastadd/Backend.jadd b/spec/jastadd/Backend.jadd
index bd2e2903586c1bfdf76f0c3850fee9e53a753504..5d4404445f0ea075eb6f3e4d6d48ef53d304603c 100644
--- a/spec/jastadd/Backend.jadd
+++ b/spec/jastadd/Backend.jadd
@@ -200,37 +200,39 @@ aspect BackendBidirectionalAPI {
 
 		if (l.multiplicityOne()) {
 			if (r.multiplicityOne()) {
-				l.generateBiOne(sb, false);
-				r.generateBiOne(sb, false);
+				l.generateBiOneOne(sb, false);
+				r.generateBiOneOne(sb, false);
 			} else if (r.multiplicityOpt()) {
-				l.generateBiOne(sb, false);
-				r.generateBiOne(sb, true);
+				l.generateBiOneOne(sb, false);
+				r.generateBiOneOne(sb, true);
 			} else if (r.multiplicityMany()) {
-
+				l.generateBiOneMany(sb);
+				r.generateBiManyOne(sb);
 			}
 		} else if (l.multiplicityOpt()) {
 			if (r.multiplicityOne()) {
-				l.generateBiOne(sb, true);
-				r.generateBiOne(sb, false);
+				l.generateBiOneOne(sb, true);
+				r.generateBiOneOne(sb, false);
 			} else if (r.multiplicityOpt()) {
-				l.generateBiOne(sb, true);
-				r.generateBiOne(sb, true);
+				l.generateBiOneOne(sb, true);
+				r.generateBiOneOne(sb, true);
 			} else if (r.multiplicityMany()) {
 				
 			}
 		} else if (l.multiplicityMany()) {
 			if (r.multiplicityOne()) {
-
+				l.generateBiManyOne(sb);
+				r.generateBiOneMany(sb);
 			} else if (r.multiplicityOpt()) {
 
 			} else if (r.multiplicityMany()) {
-				l.generateBiMany(sb);
-				r.generateBiMany(sb);
+				l.generateBiManyMany(sb);
+				r.generateBiManyMany(sb);
 			}
 		}
 	}
 
-	public void RelationComponent.generateBiOne(StringBuilder sb, boolean isOpt) {
+	public void RelationComponent.generateBiOneOne(StringBuilder sb, boolean isOpt) {
 		// Get
 		sb.append(ind(1) + "public " + ofTypeDecl() + " " + toTypeDecl());
 		sb.append("." + name() + "() {\n");
@@ -268,7 +270,7 @@ aspect BackendBidirectionalAPI {
 		}
 	}
 
-	public void RelationComponent.generateBiMany(StringBuilder sb) {
+	public void RelationComponent.generateBiManyMany(StringBuilder sb) {
 		// Get
 		sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl());
 		sb.append("." + name() + "() {\n");
@@ -310,6 +312,79 @@ aspect BackendBidirectionalAPI {
 		sb.append(ind(2) + "}\n");
 		sb.append(ind(1) + "}\n");
 	}
+
+
+	public void RelationComponent.generateBiManyOne(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) + "if (o != null && o.get" + otherSide().getImplAttributeName() + "() != null) {\n");
+		sb.append(ind(3) + "ArrayList<" + ofTypeDecl() + "> list2 = o.get"
+			+ otherSide().getImplAttributeName() + "().get" + getImplAttributeName() + "();\n");
+		sb.append(ind(3) + "if (list2.remove(o))\n");
+		sb.append(ind(4) + "o.get" + otherSide().getImplAttributeName()
+			+ "().set" + getImplAttributeName() + "(list2);\n");
+		sb.append(ind(2) + "}\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) + "list.add(o);\n");
+		sb.append(ind(2) + "set" + getImplAttributeName() + "(list);\n");
+		sb.append(ind(2) + "o.set" + otherSide().getImplAttributeName() + "(this);\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) + "set" + getImplAttributeName() + "(list);\n");
+		sb.append(ind(3) + "if (o.get" + otherSide().getImplAttributeName() + "() == this) {\n");
+		sb.append(ind(4) + "o.set" + otherSide().getImplAttributeName() + "(null);\n");
+		sb.append(ind(3) + "}\n");
+		sb.append(ind(2) + "}\n");
+		sb.append(ind(1) + "}\n");
+	}
+
+	public void RelationComponent.generateBiOneMany(StringBuilder sb) {
+		// Get
+		sb.append(ind(1) + "public " + ofTypeDecl() + " " + toTypeDecl());
+		sb.append("." + name() + "() {\n");
+		sb.append(ind(2) + "return get"	+ getImplAttributeName() + "();\n");
+		sb.append(ind(1) + "}\n");
+
+		// Set
+		sb.append(ind(1) + "public void " + toTypeDecl() + ".set" + nameCapitalized()
+			+ "(" + ofTypeDecl() + " o) {\n");
+		sb.append(ind(2) + "assertNotNull(o);\n");
+		sb.append(ind(2) + "if (get" + getImplAttributeName() + "() != null) {\n");
+		sb.append(ind(3) + "ArrayList<" + toTypeDecl() + "> list2 = get" + getImplAttributeName()
+			+ "()." + "get" + otherSide().getImplAttributeName() + "();\n");
+		sb.append(ind(3) + "list2.remove(this);\n");
+		sb.append(ind(3) + "get" + getImplAttributeName() + "()." + "set"
+			+ otherSide().getImplAttributeName() + "(list2);\n");
+		sb.append(ind(2) + "}\n");
+		sb.append(ind(2) + "set" + getImplAttributeName() + "(o);\n");
+		sb.append(ind(2) + "ArrayList<" + toTypeDecl() + "> list = o.get"
+			+ otherSide().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) + "list.add(this);\n");
+		sb.append(ind(2) + "o.set" + otherSide().getImplAttributeName() + "(list);\n");
+		sb.append(ind(1) + "}\n");
+	}
 }
 
 
diff --git a/test/Test.java b/test/Test.java
index 10651e44e3757b5b59320c16ad4a54a6b40c85e2..e63a480e945e26c38a1fca112009585e4dca7463 100644
--- a/test/Test.java
+++ b/test/Test.java
@@ -191,6 +191,48 @@ public class Test {
 	 * rel A.bi3 <-> B.bi3*;
 	 */
 	private void testBi3() {
+		setup();
+		a2.setBi3(b2);
+
+		assertNull(a1.bi3());
+		assertSame(a2.bi3(), b2);
+		assertEquals(b1.bi3(), Arrays.asList());
+		assertEquals(b2.bi3(), Arrays.asList(a2));
+		assertEquals(b3.bi3(), Arrays.asList());
+
+		a2.setBi3(b3);
+
+		assertNull(a1.bi3());
+		assertSame(a2.bi3(), b3);
+		assertEquals(b1.bi3(), Arrays.asList());
+		assertEquals(b2.bi3(), Arrays.asList());
+		assertEquals(b3.bi3(), Arrays.asList(a2));
+
+		a1.setBi3(b3);
+		a3.setBi3(b3);
+
+		assertSame(a1.bi3(), b3);
+		assertSame(a2.bi3(), b3);
+		assertSame(a3.bi3(), b3);
+		assertEquals(b1.bi3(), Arrays.asList());
+		assertEquals(b2.bi3(), Arrays.asList());
+		assertEquals(b3.bi3(), Arrays.asList(a2, a1, a3));
+
+		a2.setBi3(b1);
+
+		assertSame(a1.bi3(), b3);
+		assertSame(a2.bi3(), b1);
+		assertSame(a3.bi3(), b3);
+		assertEquals(b1.bi3(), Arrays.asList(a2));
+		assertEquals(b2.bi3(), Arrays.asList());
+		assertEquals(b3.bi3(), Arrays.asList(a1, a3));
+
+		try {
+			a2.setBi3(null);
+			check(false, "exception should be thrown");
+		} catch (Exception e) {
+			// OK
+		}
 	}
 
 
@@ -281,6 +323,47 @@ public class Test {
 	 * rel A.bi7* <-> B.bi7;
 	 */
 	private void testBi7() {
+		setup();
+		a2.addToBi7(b2);
+
+		assertEquals(a1.bi7(), Arrays.asList());
+		assertEquals(a2.bi7(), Arrays.asList(b2));
+		assertNull(b1.bi7());
+		assertSame(b2.bi7(), a2);
+		assertNull(b3.bi7());
+
+		a2.addToBi7(b3);
+		a1.addToBi7(b2);
+
+		assertEquals(a1.bi7(), Arrays.asList(b2));
+		assertEquals(a2.bi7(), Arrays.asList(b3));
+		assertNull(b1.bi7());
+		assertSame(b2.bi7(), a1);
+		assertSame(b3.bi7(), a2);
+
+		a1.addToBi7(b1);
+
+		assertEquals(a1.bi7(), Arrays.asList(b2, b1));
+		assertEquals(a2.bi7(), Arrays.asList(b3));
+		assertSame(b1.bi7(), a1);
+		assertSame(b2.bi7(), a1);
+		assertSame(b3.bi7(), a2);
+
+		a1.addToBi7(b1);
+
+		assertEquals(a1.bi7(), Arrays.asList(b2, b1));
+		assertEquals(a2.bi7(), Arrays.asList(b3));
+		assertSame(b1.bi7(), a1);
+		assertSame(b2.bi7(), a1);
+		assertSame(b3.bi7(), a2);
+
+		a1.removeFromBi7(b1);
+
+		assertEquals(a1.bi7(), Arrays.asList(b2));
+		assertEquals(a2.bi7(), Arrays.asList(b3));
+		assertNull(b1.bi7());
+		assertSame(b2.bi7(), a1);
+		assertSame(b3.bi7(), a2);
 	}