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 user-defined WSContext variable is used to check if the request body exists. The WSOptional attribute is set on the parameter (rec) for input sent in the request body.

You must code in the function to have WSContext detect whether the client has sent a body at runtime. If the request does not have an input body parameter, the GWS sets the "NoRequestBody" entry in the WSContext variable to true.

The function needs to receive data of the required structure in either a JSON or XML representation.

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