Example usage - building service interface

This section contains a few examples for the usage of the Java RSC API.

See section RSC (Remote Service Calls) for further information of available RSC services and their usage.

If you want to provide your RSC service through Java the following points must be taken into consideration.

Service

The first step to provide a service in Java is to create an interface file for the service. Afterwards you must add the com.phoenixcontact.ade.commonremoting.RemotingService annotation. This is required to identify the associated RSC service.

 

The namespace of the Java service interface file may differ from the namespace on the PLCnext device. In this case you have to define the service name in the RemotingService annotation.

The service provider name can be defined by the serviceProviderName field of the RemotingService annotation.

@RemotingService(fullName = "Ade.CommonRemoting.Security.Services.IPasswordAuthenticationService",
    serviceProviderName = "Security")
public interface IPasswordAuthenticationService {
  ...
} 

Service method

The methods should have the com.phoenixcontact.ade.commonremoting.RemotingMethod annotation. The annotation allows to specify the method index which is required to identify the method on the PLCnext device.

 

@RemotingMethod(index = 1)
void start();
@RemotingMethod(index = 2)
void stop();


If the return value of the method is an unsigned type the AdeMarshalAs annotation must be added to the method. If parameters are unsigned the AdeMarshalAs annotation must be placed right before the parameter. See for more info the sections “Data Types” and “AdeMarshalAs”.

 

@RemotingMethod(index = 1)
@AdeMarshalAs(coreType = CoreType.U4)
long exampleOne(int arg0);
@RemotingMethod(index = 2)
int example(@AdeMarshalAs(coreType = CoreType.U4) long arg0);

Data types

The following table lists the data types used in Java. For unsigned data types the next larger datatype is used e.g. for the data type uint16 the data type int32 will be used in Java.

 

Exception: There are many cases where it does not matter whether a byte or byte array is signed or unsigned. Therefore unsigned bytes are allowed to be passed as signed bytes in the Java implementation. As a result unsigned byte arrays can be passed as signed short array or signed byte array.

 

RSC Type ID C++ C# JAVA Note
Void 1 void System.Void void  
Bool 2 Arp::boolean System.Boolean boolean  
Int8 4 Arp::int8 System.SByte byte  
Uint8 5 Arp::uint8 System.Byte short (or) byte  
Int16 6 Arp::int16 System.Int16 short  
Uint16 7 Arp::uint16 System.Uint16 int  
Int32 8 Arp::int32 System.Int32 int  
Uint32 9 Arp::uint32 System.Uint32 long  
Int64 10 Arp::int64 System.Int64 long  
Uint64 11 Arp::uint64 System.Uint64 BigInteger  
Real32 12 Arp::float32 System.Single float IEEE 754
Real64 13 Arp::float64 System.Double double IEEE 754
String 14 RscString System.String String  
Struct 18 IRscSerializable struct class  
Utf8string 19 RscString System.String String  
Array 20 std::vector<T> IRscReadEnumerator IRscWriteEnumerator T[] T[]  
DateTime 23 Arp::DateTime System.DateTime java.time.Instant  
Object 28 RscVariant System.Object com.phoenixcontact.ade.commonremoting.utils.AdeObject    Wrapper object to pass the type information. Required for unsigned data types.  
Stream 34 RscStream System.IO.Stream java.io.InputStream  
Enumerator 35 IRscReadEnumerator IRscWriteEnumerator System.Collections.IEnumerator java.util.List<T>  

SecureString

36 SecureString System.Security.SecureString char[]  
      System.Version com.phoenixcontact.ade.commonremoting.Version  
      System.Guid java.util.UUID  

 

Structs

There are no structs in Java. Therefore structs are converted to Java as classes. The fields are marked as private and provided with getters and setters for access. To recognize that the class is a conversion of a struct object, the Struct annotation must be added to the class.

@com.phoenixcontact.ade.commonremoting.utils.Struct
public class ReadItem {
  private DataAccessError error;
  private AdeObject value;
  public DataAccessError getError() {
    return error;
  }
  public void setError(DataAccessError error) {
    this.error = error;
  }
  public AdeObject getValue() {
    if (value == null) {
      value = new AdeObject(null, CoreType.VOID);
    }
    return value;
  }
  public void setValue(AdeObject value) {
    this.value = value;
  }
}


The annotation com.phoenixcontact.ade.commonremoting.StructField(ignore = true) allows you to exclude fields for the serialization.
If a field is an unsigned type, you have to add the AdeMarhsalAs to the field with the corresponding CoreType.

The API implementation com.phoenixcontact.commonremoting.implementation uses reflection to access the fields.

Enums

All enums must be able to be converted to a numeric value for communication. If zero is passed as value for an enum, the enum class should contain an enum constant NONE or an enum constant with the value 0 which will be used as default value.
The enums which shall be used in the communication must implement the interface com.phoenixcontact.ade.commonremoting.utils.NumericEnum

@AdeMarshalAs(coreType = CoreType.U4)
public enum ExampleEnum implements NumericEnum<Long> {
  NONE(0);
  private long value;
  private ExampleEnum(long value) {
    this.value = value;
  }
  @Override
  public Long getValue() {
    return value;
  }
}

 

AdeMarshalAs

The com.phoenixcontact.ade.commonremoting.AdeMarshalAs annotation allows you

  • to define the marshal type of a string (ASCII, UTF-8, UTF-16) (Default is UTF-8)
  • to define the max length in bytes for a string
  • to define the core type of a field, parameter and return value. This is necessary for unsigned types.
@AdeMarshalAs(marshalType = AdeMarshalType.ANSI)
String asciiString;
@AdeMarshalAs(marshalType = AdeMarshalType.UTF_8, stringLength = 256)
String utf8String;
@AdeMarshalAs(marshalType = AdeMarshalType.UTF_16)
String utf16String;
boolean valueBoolean;
byte valueInt8;
@AdeMarshalAs(coreType = CoreType.U1)
byte valueUInt8
@AdeMarshalAs(coreType = CoreType.U1)
short valueUInt8
short valueInt16;
@AdeMarshalAs(coreType = CoreType.U2)
int valueUInt16
int valueInt32;
@AdeMarshalAs(coreType = CoreType.U4)
long valueUInt32
long valueInt64;
@AdeMarshalAs(coreType = CoreType.U8)
BigInteger valueUInt64
float valueReal32;
double valueReal64;
AdeObject valueObject;
@AdeMarshalAs(coreType = CoreType.U1)
byte[] byteArray;
@AdeMarshalAs(coreType = CoreType.U1)
short[] byteArray;
int[] valueInt32Array;
@AdeMarshalAs(componentCoreType = CoreType.U4)
long[] valueUInt32Array;
List<Short> valueInt16List;
List<@AdeMarshalAs(coreType = CoreType.U2) Integer> valueUInt16List;
InputStream valueStream;
Instant valueDateTime;
@AdeMarshalAs(marshalType = AdeMarshalType.LOCAL_DATE_TIME)
Instant valueLocalDateTime;

 

OutParam

The com.phoenixcontact.ade.commonremoting.utils.OutParam class provides you with the possibility to define methods, e.g.:

void example(OutParam<Integer> param);
void example(OutParam<@AdeMarshalAs(coreType = CoreType.U4)> Long param);
void example(OutParam<@AdeMarshalAs(coreType = CoreType.U1)> short[] param);
void example(OutParam<@AdeMarshalAs(coreType = CoreType.U1)> byte[] param);

 

RefParam

The com.phoenixcontact.ade.commonremoting.utils.RefParam class provides you with possibility to define methods, e.g.:

void example(RefParam<Integer> param);
void example(RefParam<@AdeMarshalAs(coreType = CoreType.U4) Long> param);