RO : Java. Methods returning results do not read the result in the same order as it was written

I have quite a lot of server methods which return a structure as an ‘out’ parameter and which also return a boolean result. The delphi server writes the result to stream before the out param complex type. The Java client reads the result after the complex type. This of course leads to various stream read errors.

Delphi server source

procedure TsvcAndroidTest_Invoker.Invoke_getTestStructWithBoolResult(const __Instance:IInterface; const __Message:IROMessage; const __Transport:IROTransport; out __oResponseOptions:TROResponseOptions);
{ function getTestStructWithBoolResult(out aTestStruct: TestComplexType): Boolean; }
var
  aTestStruct: LibAndroidTest_Intf.TestComplexType;
  lResult: Boolean;
  __lObjectDisposer: TROObjectDisposer;
begin
  aTestStruct := nil;
  try

    lResult := (__Instance as IsvcAndroidTest).getTestStructWithBoolResult(aTestStruct);

    __Message.InitializeResponseMessage(__Transport, 'LibAndroidTest', 'svcAndroidTest', 'getTestStructWithBoolResultResponse');
    __Message.Write('Result', TypeInfo(Boolean), lResult, []);
    __Message.Write('aTestStruct', TypeInfo(LibAndroidTest_Intf.TestComplexType), aTestStruct, []);
    __Message.Finalize;
    __Message.UnsetAttributes(__Transport);

  finally
    __lObjectDisposer := TROObjectDisposer.Create(__Instance);
    try
      __lObjectDisposer.Add(aTestStruct);
    finally
      __lObjectDisposer.Free();
    end;
  end;
end;

Android java client source. Note that the result is read after the complex type.

  @Override
  public Boolean getTestStructWithBoolResult(
    ReferenceType _aTestStruct
    ) {
    Message _localMessage = getProxyMessage();
    _localMessage.initializeAsRequestMessage("LibAndroidTest", _getActiveInterfaceName(), "getTestStructWithBoolResult");
    try {
      _localMessage.finalizeMessage();
      getProxyClientChannel().dispatch(_localMessage);
      
     
      _aTestStruct.setValue((TestComplexType)_localMessage.readComplex("aTestStruct", TestComplexType.class));
      return (Boolean)_localMessage.readBoolean("Result");
    } finally {
      synchronized (getProxyMessage()) {
        getProxyMessage().setClientID(_localMessage.getClientID());
      }
      _localMessage.clear();
    }
  }

Altered working code

  @Override
  public Boolean getTestStructWithBoolResult(
    ReferenceType _aTestStruct
    ) {
    Message _localMessage = getProxyMessage();
    _localMessage.initializeAsRequestMessage("LibAndroidTest", _getActiveInterfaceName(), "getTestStructWithBoolResult");
    try {
      _localMessage.finalizeMessage();
      getProxyClientChannel().dispatch(_localMessage);
      
      
      Boolean resBool = (Boolean)_localMessage.readBoolean("Result"); 
      _aTestStruct.setValue((TestComplexType)_localMessage.readComplex("aTestStruct", TestComplexType.class));
      return resBool;
    } finally {
      synchronized (getProxyMessage()) {
        getProxyMessage().setClientID(_localMessage.getClientID());
      }
      _localMessage.clear();
    }
  }

Regards,
Will.

Thank you for the report. The issue has been logged for further review (#55552).

Best regards.

Will,

thanx for the report; i agree this is a critical bug; we’ll need to adress that for the upcoming May12 release.

Hello Will,

Fixed. The change will go into the next gamma build.
Attaching changed template files for you to use with codegen2 command line utility, if you don’t want to wait until the gamma build published.

Best regards - Sergey.

Thanks for the fast response. I will give it a try and let you know how it goes.

Regards,
Will.

That fix doesn’t work. It gives unreachable code errors in Eclipse because the return method is being called before the ‘out’ parameter is read out. Note in the fix I gave that the return value is assigned to a variable and the return statement is still made last.

Regards,
Will.

I have changed the supplied template file for java from line 609 with the following and get working code. (can I have a job…)

      // <%%% START IF_FUNCTION %%%>
      // <%%% START IF_RESULT_COMPLEX %%%>
      %OPERATION_RESULT_TYPE% aResult =  (%OPERATION_RESULT_TYPE%)_localMessage.read%OPERATION_RESULT_READER_WRITER%("%OPERATION_RESULT_NAME%", %OPERATION_RESULT_TYPE%.class);
      // <%%% END IF_RESULT_COMPLEX %%%>
      // <%%% START IF_RESULT_ENUM %%%>
      %OPERATION_RESULT_TYPE% aResult = %OPERATION_RESULT_TYPE%.values()[_localMessage.read%OPERATION_RESULT_READER_WRITER%("%OPERATION_RESULT_NAME%")];
      // <%%% END IF_RESULT_ENUM %%%>
      // <%%% START IF_RESULT_SIMPLE %%%>
      %OPERATION_RESULT_TYPE% aResult = (%OPERATION_RESULT_TYPE%)_localMessage.read%OPERATION_RESULT_READER_WRITER%("%OPERATION_RESULT_NAME%");
      // <%%% END IF_RESULT_SIMPLE %%%>
      // <%%% END IF_FUNCTION %%%>
      // <%%% START IF_OPERATION_HAS_OUT_PARAMS %%%>
      // <%%% START OUT_PARAMS_NO_STRIP %%%>
      // <%%% START IF_PARAM_TYPE_COMPLEX %%%>
      _%PARAM_NAME%.setValue((%PARAM_TYPE%)_localMessage.read%PARAM_READER_WRITER%("%PARAM_NAME%", %PARAM_TYPE%.class));
      // <%%% END IF_PARAM_TYPE_COMPLEX %%%>
      // <%%% START IF_PARAM_TYPE_ENUM %%%>
      _%PARAM_NAME%.setValue(%PARAM_TYPE%.values()[_localMessage.read%PARAM_READER_WRITER%("%PARAM_NAME%")]);
      // <%%% END IF_PARAM_TYPE_ENUM %%%>
      // <%%% START IF_PARAM_TYPE_SIMPLE %%%>
      _%PARAM_NAME%.setValue((%PARAM_TYPE%)_localMessage.read%PARAM_READER_WRITER%("%PARAM_NAME%"));
      // <%%% END IF_PARAM_TYPE_SIMPLE %%%>
      // <%%% END OUT_PARAMS_NO_STRIP %%%>
      // <%%% END IF_OPERATION_HAS_OUT_PARAMS %%%>
      // <%%% START IF_FUNCTION %%%>
      // <%%% START IF_RESULT_COMPLEX %%%>
      return aResult;
      // <%%% END IF_RESULT_COMPLEX %%%>
      // <%%% START IF_RESULT_ENUM %%%>
      return aResult;
      // <%%% END IF_RESULT_ENUM %%%>
      // <%%% START IF_RESULT_SIMPLE %%%>
      return aResult;
      // <%%% END IF_RESULT_SIMPLE %%%>
      // <%%% END IF_FUNCTION %%%>

reopened; my apologies for this.

Hello Will,

Will_Honor said: That fix doesn't work. It gives unreachable code errors in Eclipse
Ah, sorry. This worked for Oxygene language only because it has 'Result' variable implicitly defined inside any function. Your fix is proper, thanks. The only thing I would do is to shorten the last <%%% START IF_FUNCTION %%%> block, there is no need to have 3 alternatives, so:
// <%%% START IF_FUNCTION %%%>
return aResult;
// <%%% END IF_FUNCTION %%%>

Best regards - Sergey.