public Object basicBridgePutIfAbsent(final Object key, Object value, boolean isObject,
      Object callbackArg, final ClientProxyMembershipID client, boolean fromClient,
      EntryEventImpl clientEvent)
      throws TimeoutException, EntryExistsException, CacheWriterException {

    EventID eventId = clientEvent.getEventId();
    long startPut = getStatisticsClock().getTime();

    @Released
    final EntryEventImpl event =
        entryEventFactory.create(this, Operation.PUT_IF_ABSENT, key, null,
            callbackArg, false, client.getDistributedMember(), true, eventId);

    try {
      event.setContext(client);

      // if this is a replayed operation we may already have a version tag
      event.setVersionTag(clientEvent.getVersionTag());
      event.setPossibleDuplicate(clientEvent.isPossibleDuplicate());

      // Set the new value to the input byte[] if it isn't null
      if (value != null) {
        // If the byte[] represents an object, then store it serialized
        // in a CachedDeserializable; otherwise store it directly as a byte[]
        if (isObject) {
          // The value represents an object
          event.setSerializedNewValue((byte[]) value);
        } else {
          // The value does not represent an object
          event.setNewValue(value);
        }
      }

      validateArguments(key, event.basicGetNewValue(), callbackArg);

      // cannot overwrite an existing key
      boolean ifNew = true;
      // can create a new key
      boolean ifOld = false;
      // need the old value if the create fails
      boolean requireOldValue = true;

      boolean basicPut = basicPut(event, ifNew, ifOld, null, requireOldValue);

      getCachePerfStats().endPut(startPut, false);
      stopper.checkCancelInProgress(null);

      Object oldValue = event.getRawOldValueAsHeapObject();
      if (oldValue == Token.NOT_AVAILABLE) {
        oldValue = AbstractRegion.handleNotAvailable(oldValue);
      }

      if (basicPut) {
        clientEvent.setVersionTag(event.getVersionTag());
        clientEvent.isConcurrencyConflict(event.isConcurrencyConflict());
      } else {
        if (oldValue == null) {
          // putIfAbsent on server can return null if the
          // operation was not performed (oldValue in cache was null).
          // We return the INVALID token instead of null to distinguish
          // this case from successful operation
          return Token.INVALID;
        }
      }
      return oldValue;
    } finally {
      event.release();
    }
  }
Same as {@link #replace(Object, Object)} except a callback argument is supplied to be passed on
to <tt>CacheListener</tt>s and/or <tt>CacheWriter</tt>s.
<p>
TODO: callbackArg is always null but this method is for callbacks??
geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java