diff --git a/spec/jastadd/Backend.jadd b/spec/jastadd/Backend.jadd
index 5d4404445f0ea075eb6f3e4d6d48ef53d304603c..d9da1c4ef99e9ff0d081994bcd326aebfc00075d 100644
--- a/spec/jastadd/Backend.jadd
+++ b/spec/jastadd/Backend.jadd
@@ -206,7 +206,7 @@ aspect BackendBidirectionalAPI {
 				l.generateBiOneOne(sb, false);
 				r.generateBiOneOne(sb, true);
 			} else if (r.multiplicityMany()) {
-				l.generateBiOneMany(sb);
+				l.generateBiOneMany(sb, false);
 				r.generateBiManyOne(sb);
 			}
 		} else if (l.multiplicityOpt()) {
@@ -217,14 +217,16 @@ aspect BackendBidirectionalAPI {
 				l.generateBiOneOne(sb, true);
 				r.generateBiOneOne(sb, true);
 			} else if (r.multiplicityMany()) {
-				
+				l.generateBiOneMany(sb, true);
+				r.generateBiManyOne(sb);
 			}
 		} else if (l.multiplicityMany()) {
 			if (r.multiplicityOne()) {
 				l.generateBiManyOne(sb);
-				r.generateBiOneMany(sb);
+				r.generateBiOneMany(sb, false);
 			} else if (r.multiplicityOpt()) {
-
+				l.generateBiManyOne(sb);
+				r.generateBiOneMany(sb, true);
 			} else if (r.multiplicityMany()) {
 				l.generateBiManyMany(sb);
 				r.generateBiManyMany(sb);
@@ -357,7 +359,7 @@ aspect BackendBidirectionalAPI {
 		sb.append(ind(1) + "}\n");
 	}
 
-	public void RelationComponent.generateBiOneMany(StringBuilder sb) {
+	public void RelationComponent.generateBiOneMany(StringBuilder sb, boolean isOpt) {
 		// Get
 		sb.append(ind(1) + "public " + ofTypeDecl() + " " + toTypeDecl());
 		sb.append("." + name() + "() {\n");
@@ -367,7 +369,9 @@ aspect BackendBidirectionalAPI {
 		// Set
 		sb.append(ind(1) + "public void " + toTypeDecl() + ".set" + nameCapitalized()
 			+ "(" + ofTypeDecl() + " o) {\n");
-		sb.append(ind(2) + "assertNotNull(o);\n");
+		if (!isOpt) {
+			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");
@@ -376,14 +380,30 @@ aspect BackendBidirectionalAPI {
 			+ 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"
+
+		int ind = isOpt ? 3 : 2;
+		if (isOpt) {
+			sb.append(ind(2) + "if (o != null) {\n");
+		}
+		sb.append(ind(ind) + "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(ind) + "if (list == null) {\n");
+		sb.append(ind(ind+1) + "list = new ArrayList<>();\n");
+		sb.append(ind(ind) + "}\n");
+		sb.append(ind(ind) + "list.add(this);\n");
+		sb.append(ind(ind) + "o.set" + otherSide().getImplAttributeName() + "(list);\n");
+		if (isOpt) {
+			sb.append(ind(2) + "}\n");
+		}
 		sb.append(ind(1) + "}\n");
+
+		// has
+		if (isOpt) {
+			sb.append(ind(1) + "public boolean " + toTypeDecl());
+			sb.append(".has" + nameCapitalized() + "() {\n");
+			sb.append(ind(2) + "return " + name() + "() != null;\n");
+			sb.append(ind(1) + "}\n");
+		}
 	}
 }
 
diff --git a/test/Test.java b/test/Test.java
index e63a480e945e26c38a1fca112009585e4dca7463..fe6be7882cba6f9fda9bcb08496fd6b5933d3c37 100644
--- a/test/Test.java
+++ b/test/Test.java
@@ -315,6 +315,54 @@ public class Test {
 	 * rel A.bi6? <-> B.bi6*;
 	 */
 	private void testBi6() {
+		setup();
+		a2.setBi6(b2);
+
+		assertNull(a1.bi6());
+		assertSame(a2.bi6(), b2);
+		assertEquals(b1.bi6(), Arrays.asList());
+		assertEquals(b2.bi6(), Arrays.asList(a2));
+		assertEquals(b3.bi6(), Arrays.asList());
+
+		a2.setBi6(b3);
+
+		assertNull(a1.bi6());
+		assertSame(a2.bi6(), b3);
+		assertEquals(b1.bi6(), Arrays.asList());
+		assertEquals(b2.bi6(), Arrays.asList());
+		assertEquals(b3.bi6(), Arrays.asList(a2));
+
+		a1.setBi6(b3);
+		a3.setBi6(b3);
+
+		assertSame(a1.bi6(), b3);
+		assertSame(a2.bi6(), b3);
+		assertSame(a3.bi6(), b3);
+		assertEquals(b1.bi6(), Arrays.asList());
+		assertEquals(b2.bi6(), Arrays.asList());
+		assertEquals(b3.bi6(), Arrays.asList(a2, a1, a3));
+
+		a2.setBi6(b1);
+
+		assertSame(a1.bi6(), b3);
+		assertSame(a2.bi6(), b1);
+		assertSame(a3.bi6(), b3);
+		assertEquals(b1.bi6(), Arrays.asList(a2));
+		assertEquals(b2.bi6(), Arrays.asList());
+		assertEquals(b3.bi6(), Arrays.asList(a1, a3));
+
+		a2.setBi6(null);
+
+		assertSame(a1.bi6(), b3);
+		assertNull(a2.bi6());
+		assertSame(a3.bi6(), b3);
+		assertEquals(b1.bi6(), Arrays.asList());
+		assertEquals(b2.bi6(), Arrays.asList());
+		assertEquals(b3.bi6(), Arrays.asList(a1, a3));
+
+		assertTrue(a1.hasBi6());
+		assertFalse(a2.hasBi6());
+		assertTrue(a3.hasBi6());
 	}
 
 
@@ -372,6 +420,47 @@ public class Test {
 	 * rel A.bi8* <-> B.bi8?;
 	 */
 	private void testBi8() {
+		setup();
+		a2.addToBi8(b2);
+
+		assertEquals(a1.bi8(), Arrays.asList());
+		assertEquals(a2.bi8(), Arrays.asList(b2));
+		assertNull(b1.bi8());
+		assertSame(b2.bi8(), a2);
+		assertNull(b3.bi8());
+
+		a2.addToBi8(b3);
+		a1.addToBi8(b2);
+
+		assertEquals(a1.bi8(), Arrays.asList(b2));
+		assertEquals(a2.bi8(), Arrays.asList(b3));
+		assertNull(b1.bi8());
+		assertSame(b2.bi8(), a1);
+		assertSame(b3.bi8(), a2);
+
+		a1.addToBi8(b1);
+
+		assertEquals(a1.bi8(), Arrays.asList(b2, b1));
+		assertEquals(a2.bi8(), Arrays.asList(b3));
+		assertSame(b1.bi8(), a1);
+		assertSame(b2.bi8(), a1);
+		assertSame(b3.bi8(), a2);
+
+		a1.addToBi8(b1);
+
+		assertEquals(a1.bi8(), Arrays.asList(b2, b1));
+		assertEquals(a2.bi8(), Arrays.asList(b3));
+		assertSame(b1.bi8(), a1);
+		assertSame(b2.bi8(), a1);
+		assertSame(b3.bi8(), a2);
+
+		a1.removeFromBi8(b1);
+
+		assertEquals(a1.bi8(), Arrays.asList(b2));
+		assertEquals(a2.bi8(), Arrays.asList(b3));
+		assertNull(b1.bi8());
+		assertSame(b2.bi8(), a1);
+		assertSame(b3.bi8(), a2);
 	}