WSOptional

Qualifies a parameter as optional in a REST function.

Syntax

WSOptional

WSOptional is an optional attribute.

Usage

You can set WSOptional on the ATTRIBUTES()clause of a parameter when a function does not require the parameter to be present when a client calls the service. Setting parameters as optional is typically used when defining REST functions in the following situations:

Example WSCookie and WSOptional

In this sample REST function a set of users is returned based on a value provided in a cookie sent as a header. The function's ccode input parameter is set with the WSCookie, WSName, and the WSOptional attributes.

If the client application calling the function provides a value for the cookie in the request, the name specified by WSName must be set in the query string of the URI, such as http://myhost:6394/gas/ws/r/myGroup/myXcf/Accounts/usersbycountry?country=FRA

In the SQL query of the database, the COALESCE function is used to produce a query that supports the optional parameter. If the cookie is not provided, all users are returned.

WSThrows is set to handle errors. In the TRY/CATCH block, the sqlca record is checked after the execution of the SQL query. The SQLERRMESSAGE is set to the message field of the userError variable, and a call to SetRestError() returns the message defined in WSThrows for the error.

IMPORT com

TYPE profileType RECORD
     id INTEGER,
     name VARCHAR(100),
     email VARCHAR(255),
     category VARCHAR(10),
     status INTEGER,
     country VARCHAR(3)
     # ...
   END RECORD

PUBLIC DEFINE userError RECORD ATTRIBUTE(WSError = "User error")
  message STRING
END RECORD

PUBLIC FUNCTION getUsersByCountry(
     ccode STRING ATTRIBUTE(WSCookie, WSOptional, WSName = "country", 
                            WSDescription = "Country code" )
                            )
  ATTRIBUTES (WSGet,
              WSPath = "/usersbycountry",
              WSDescription = "Gets users with the optional cookie value applied.",
              WSThrows = "400:Invalid,406:@userError" )
   RETURNS ( DYNAMIC ARRAY ATTRIBUTE(WSName = "Users",
             WSMedia = "application/json") OF profileType)
      
     DEFINE arr DYNAMIC ARRAY OF profileType
     DEFINE i INTEGER = 1
     TRY
       # code to get users
       DECLARE c4 CURSOR FOR SELECT * FROM users
                               WHERE users.country = COALESCE(ccode,users.country)
                               ORDER BY users.name ASC         
       # COALESCE function is used to produce a query that supports the optional parameter
       FOREACH c4 INTO arr[i].*
         LET i = i+1
       END FOREACH
       CALL arr.deleteElement(arr.getLength())
       # Remove the empty element implied by reference in FOREACH loop
     CATCH
       LET userError.message = SFMT("Error in SQL execution: %1 [%2]", sqlca.sqlcode, SQLERRMESSAGE )
       CALL com.WebServiceEngine.SetRestError(406,userError)
     END TRY
     RETURN arr
END FUNCTION

Example: Optional input body

In this sample REST function the value returned is dependent on whether data has been received in an input body. The function has an input parameter rec that is set with the WSOptional attribute. Therefore, data may or may not be received in the request body.

A user-defined variable Context set with the WSContext attribute is defined in the module. This is used to detect if the client has sent a body at runtime. If the request does not have an input body, the GWS sets the "NoRequestBody" entry in the Context variable to true.

In the function the Context is checked for the status of the "NoRequestBody" entry, and the value the function returns is based on this.

PRIVATE DEFINE Context DICTIONARY ATTRIBUTES(WSContext) OF STRING

PUBLIC
FUNCTION testRecord(rec RECORD ATTRIBUTES(WSOptional) a INTEGER, b INTEGER END RECORD)
  ATTRIBUTES (WSPut, 
             WSPath = "/record",
             WSDescription = "Check for request body with WSContext variable")
  RETURNS (INTEGER)
  IF Context.contains("NoRequestBody") THEN
    DISPLAY Context["NoRequestBody"]
    RETURN 0
  ELSE
     RETURN rec.a + rec.b
  END IF
END FUNCTION