diff --git a/ragconnect.base/src/main/jastadd/Mappings.jrag b/ragconnect.base/src/main/jastadd/Mappings.jrag
index b5569995f579ac097cc78bac9a2980775affa39a..9fd55aa4cad7eb22f75913f7942b547ca91ddec2 100644
--- a/ragconnect.base/src/main/jastadd/Mappings.jrag
+++ b/ragconnect.base/src/main/jastadd/Mappings.jrag
@@ -183,6 +183,10 @@ aspect Mappings {
   }
 
   // --- isPrimitiveType ---
+  syn boolean EndpointDefinition.isPrimitiveType() = getEndpointTarget().isPrimitiveType();
+  syn boolean EndpointTarget.isPrimitiveType() = false;
+  eq TokenEndpointTarget.isPrimitiveType() = getToken().isPrimitiveType();
+  eq AttributeEndpointTarget.isPrimitiveType() = new SimpleJavaTypeUse(getTypeName()).isPrimitiveType();
   syn boolean TokenComponent.isPrimitiveType() = effectiveJavaTypeUse().isPrimitiveType();
   syn boolean JavaTypeUse.isPrimitiveType() = false;
   eq SimpleJavaTypeUse.isPrimitiveType() {
diff --git a/ragconnect.base/src/main/resources/mappingApplication.mustache b/ragconnect.base/src/main/resources/mappingApplication.mustache
index 31cd12365e1158425f45c2666d86faa0bee14c0e..482d54783782ada82cacd9ce75b81d30c1e21e68 100644
--- a/ragconnect.base/src/main/resources/mappingApplication.mustache
+++ b/ragconnect.base/src/main/resources/mappingApplication.mustache
@@ -1,6 +1,10 @@
+{{#Send}}
+{{^PrimitiveType}}
 if ({{firstInputVarName}} == null) {
   {{preemptiveReturn}}
 }
+{{/PrimitiveType}}
+{{/Send}}
 {{{lastDefinitionToType}}} {{lastResult}};
 try {
   {{#innerMappingDefinitions}}
diff --git a/ragconnect.base/src/main/resources/sendDefinition.mustache b/ragconnect.base/src/main/resources/sendDefinition.mustache
index b066c690444a48cb8aadd64ccdd2dcdc2a46f78d..ba6661bb20daa90926eba165121a8e8aeb400293 100644
--- a/ragconnect.base/src/main/resources/sendDefinition.mustache
+++ b/ragconnect.base/src/main/resources/sendDefinition.mustache
@@ -14,7 +14,13 @@ public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParamete
         {{#configLoggingEnabledForWrites}}
         {{logDebug}}("[Send] {{entityName}} = {{log_}} -> {{log_}}", {{getterMethodCall}}, {{connectParameterName}});
         {{/configLoggingEnabledForWrites}}
-        handler.publish(topic, {{lastValueGetterCall}});
+        if ({{lastValueGetterCall}} != null) {
+          handler.publish(topic, {{lastValueGetterCall}});
+        {{#configLoggingEnabledForWrites}}
+        } else {
+          {{logWarn}}("[Send] {{entityName}} -> {{log_}}: can't send null.", {{connectParameterName}});
+        {{/configLoggingEnabledForWrites}}
+        }
         }{{#IndexBasedListAccess}}, index{{/IndexBasedListAccess}}, connectToken);
       {{updateMethodName}}({{#IndexBasedListAccess}}index{{/IndexBasedListAccess}});
       if (writeCurrentValue) {
diff --git a/ragconnect.tests/build.gradle b/ragconnect.tests/build.gradle
index 1c80e4eb08857cd472fec4ef64cfd8b029cbfcb0..821617bef166830e8c3710b81034a6e962073ee1 100644
--- a/ragconnect.tests/build.gradle
+++ b/ragconnect.tests/build.gradle
@@ -667,6 +667,7 @@ task compileRelationIncremental(type: RagConnectTest) {
         inputFiles = [file('src/test/01-input/relation/Test.relast'),
                       file('src/test/01-input/relation/Test.connect')]
         rootNode = 'Root'
+        logWrites = true
         extraOptions = defaultRagConnectOptionsAnd(['--experimental-jastadd-329'])
     }
     relast {
diff --git a/ragconnect.tests/src/test/01-input/relation/Test.connect b/ragconnect.tests/src/test/01-input/relation/Test.connect
index 5fdc1f08be19d29600f4c1a314114cfae7cdf99c..b122934e2a7ea82ac6923a1426cb96da90fe9aaf 100644
--- a/ragconnect.tests/src/test/01-input/relation/Test.connect
+++ b/ragconnect.tests/src/test/01-input/relation/Test.connect
@@ -15,13 +15,13 @@ send SenderRoot.BiOptionalB using ConcatValues;
 send SenderRoot.BiListB using ConcatValueList;
 
 ConcatValues maps B b to String {:
-  return b.getValue() + b.getInner().getInnerValue();
+  return b.getValue() + "+" + b.getInner().getInnerValue();
 :}
 
 ConcatValueList maps java.util.List<B> list to String {:
   StringBuilder sb = new StringBuilder();
   for (B b : list) {
-    sb.append(b.getValue() + b.getInner().getInnerValue()).append(";");
+    sb.append(b.getValue() + "+" + b.getInner().getInnerValue()).append(";");
   }
   return sb.toString();
 :}
diff --git a/ragconnect.tests/src/test/01-input/relation/Test.jadd b/ragconnect.tests/src/test/01-input/relation/Test.jadd
index 9ed81e10ad62435704b667aabc5624e2dd959a61..3e202c02575049c2809f9bd608eb424537093393 100644
--- a/ragconnect.tests/src/test/01-input/relation/Test.jadd
+++ b/ragconnect.tests/src/test/01-input/relation/Test.jadd
@@ -4,18 +4,6 @@ aspect MakeCodeCompile {
 
 }
 aspect MakeCodeWork {
-  //public boolean SenderRoot.connectMyA(String uriString, boolean sendCurrentValue) { return true; }
-  //public boolean SenderRoot.connectOptionalA(String uriString, boolean sendCurrentValue) { return true; }
-  //public boolean SenderRoot.connectListA(String uriString, boolean sendCurrentValue) { return true; }
-  //public boolean SenderRoot.connectBiMyA(String uriString, boolean sendCurrentValue) { return true; }
-  //public boolean SenderRoot.connectBiOptionalA(String uriString, boolean sendCurrentValue) { return true; }
-  //public boolean SenderRoot.connectBiListA(String uriString, boolean sendCurrentValue) { return true; }
-  //public boolean SenderRoot.connectMyB(String uriString, boolean sendCurrentValue) { return true; }
-  //public boolean SenderRoot.connectOptionalB(String uriString, boolean sendCurrentValue) { return true; }
-  //public boolean SenderRoot.connectListB(String uriString, boolean sendCurrentValue) { return true; }
-  //public boolean SenderRoot.connectBiMyB(String uriString, boolean sendCurrentValue) { return true; }
-  //public boolean SenderRoot.connectBiOptionalB(String uriString, boolean sendCurrentValue) { return true; }
-  //public boolean SenderRoot.connectBiListB(String uriString, boolean sendCurrentValue) { return true; }
 }
 aspect NameResolution {
   // overriding customID guarantees to produce the same JSON representation for equal lists
@@ -32,4 +20,13 @@ aspect NameResolution {
   protected String Inner.customID() {
     return getClass().getSimpleName() + getInnerValue();
   }
+
+  // override resolving of SenderRoot for As in ReceiverRoot
+  refine RefResolverStubs eq A.resolveToMyAByToken(String id) = getParent() != null ? resolveToMyAByTokenInh(id) : null;
+
+  inh SenderRoot A.resolveToMyAByTokenInh(String id);
+  eq SenderRoot.getA().resolveToMyAByTokenInh(String id) = globallyResolveSenderRootByToken(id);
+  eq ReceiverRoot.getChild().resolveToMyAByTokenInh(String id) = getFakeSenderRoot(id);
+
+  syn nta SenderRoot ReceiverRoot.getFakeSenderRoot(String id) = new SenderRoot();
 }
diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/RelationTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/RelationTest.java
index bf56da42b08a404357f2bd8ef8951a9b53ae3836..b8349f30943bd8d9d02e71df185367b7aa521d30 100644
--- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/RelationTest.java
+++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/RelationTest.java
@@ -6,11 +6,9 @@ import org.junit.jupiter.api.Tag;
 
 import java.io.IOException;
 import java.util.List;
-import java.util.Objects;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Predicate;
-import java.util.function.Supplier;
 
 import static java.util.function.Predicate.isEqual;
 import static org.assertj.core.api.Assertions.assertThat;
@@ -149,7 +147,7 @@ public class RelationTest extends AbstractMqttTest {
     // TODO implement test
     // TODO also check disconnect
     check(6, "a1", null, tuple(), null, null, tuple(),
-            "b1", "", tuple(), "", "", tuple());
+            "b1", null, tuple(), null, null, tuple());
   }
 
   @Override
@@ -212,11 +210,17 @@ public class RelationTest extends AbstractMqttTest {
   }
 
   private void assertNullOrB(String expected, String actual, String alias) {
-    assertEquals(Objects.requireNonNullElse(expected, ""), actual, alias);
+    final String expectedValue;
+    if (expected == null) {
+      expectedValue = "";
+    } else {
+      expectedValue = expected + "+inner" + expected;
+    }
+    assertEquals(expectedValue, actual, alias);
   }
 
   private void assertListEqualsForB(List<Object> expected, String actual, String alias) {
-    String[] actualTokens = actual.split(";");
+    String[] actualTokens = actual.isEmpty() ? new String[0] : actual.split(";");
     assertEquals(expected.size(), actualTokens.length, alias + ".size");
     for (int i = 0, expectedSize = expected.size(); i < expectedSize; i++) {
       String s = (String) expected.get(i);