What is Server Side Validation Scripts?

Server Side Validation Scripting allows CloudIO Application Developers to write custom validation code on any Data Source using Java. Unlike traditional Java development, you don't have to do a compile & run. Any changes to these scripts will be picked up by the platform at runtime without the need for an application server bounce.

Standard Java Syntax

You can use normal Java statements and expressions. Statements and expressions are the kinds of things you normally find inside of a Java method: variable assignments, method calls, math expressions, for-loops, etc.

Note: Java 1.5 syntax is now supported. Which means you can use generics.

Here are some examples:


/* Standard Java syntax*/ // Use a hashtable Hashtable hashtable = new Hashtable(); Date date = new Date(); hashtable.put( "today", date ); // assign the current clock value long millisecs = System.currentTimeMillis(); // Loop int add = 0; for (int i=0; i<5; i++) { add += i; }

Exception Handling

Exception handling using try/catch blocks works just as it does in Java.

try {
    int i = 1/0;
 } catch ( ArithmeticException e ) {
   errorMsg = "Exception:"+e;
   errorTitle = "Error";
 }
if (true) {
throw new RAException("Title", "Error message");
}

Importing Classes and Packages

As in Java, you can either refer to classes by their fully qualified names, or you can import one or more classes from a Java package.

import javax.xml.parsers.*;
import mypackage.MyClass;

When do we use it?

If you want to execute pre or post conditions on the data source object's state changes, you can go with server side scripting. Apart from validations, you can also use this feature to do defaulting as well.

Note: Any defaulting performed in the Post operations (e.g. After Insert, After Update) will be updated on the UI but not persisted to the database until the user perform a Save action.

Pre and Post conditions on Datasource object are

  • Before Insert Row
  • Before Update Row
  • Before Delete Row
  • Before Validation Row
  • Before Import Row
  • After Insert Row
  • After Update Row
  • After Delete Row
  • After Validation Row

What pre-defined variables are available?

db
An instance of ScriptUtil.java
dateUtils
An instanceof DateUtils.java
user
Logged in Username
userid
Logged in User ID
subDomain
You application sub-domain
dbdata
An instanceof RPCModelData with the values populated from the database. Will be null for Insert operations
data
An instanceof RPCModelData with the values populated from the user's input
operation
I for Insert, U for update, D for delete & V for validation.
errorMsg
Initialized with empty String. Set a value if you want the operation to be stopped. This is usefull in Before Insert, Before Update etc, if you want the operations to be aborted due to some validation failures.
errorTitle
Application only when errorMsg is populated. This will be display as the title on the Error Popup Window.
Note: The above variable names are case sensitive

Why direct access to the Database Connection not available through scripting?

For obvious reasons. But you can do a query or insert/update through the ScriptUtil object ("db")

What is the alternative to get direct access to the Database Connection object?

In-order to use the Database Connection object, you can implement Object Handlers.

Sample Use Cases

Update Parent DataSource when a child DataSource is updated by the user

// import the required classes
import com.rapapp.platform.client.mdata.RPCModelData; import java.sql.SQLException; try {

    // Get the parent row
    RPCModelData parentRow = data.getMaster();

    // Backup any client only attribute values so we can set it back later
    String clientOnlyAttribute = parentRow.get("clientOnlyAttribute");

    RPCModelData dbRow = db.getObjectByPKValues(
            "ParentDataSource",
            new Object[] { parentRow.get("pkAttribute1"),
                    parentRow.get("pkAttribute2") });

    // Clear all the values from the parent row
    parentRow.clearData();

    // copy values from dbRow to the parent row
    parentRow.setProperties(dbRow.getProperties());
    
    // restore the clientOnlyAttribute
    parentRow.set("clientOnlyAttribute", clientOnlyAttribute);

} catch (SQLException e) {
    // Whoops something went wrong
    errorMsg = e.getMessage();
    errorTitle = "Error Updating ParentDataSource";
}

Display some informational message to the user when a DataSource is inserted or updated

// Assuming that the message to be displayed is returned by the PL/SQL procedure in an out parameter P_MSGDATA
if (data.get("msgdata") != null){
data.setParam("im", data.getString("msgdata"));
}

// Static message
if ("Closed".equals(data.get("status")){
data.setParam("im", "Item has been closed successfully!");
}

Display error message based on some conditional validation

if ("BOOK".equals(data.getString("orderStatus"))) {

    errorTitle = "Missing Mandatory Information for Booking this Order";

    if ("CREDIT_CARD".equals(data.getString("Payment Type Code"))
            && data.getDouble("total").doubleValue() > 0.0d) {
        if (data.getDate("credit card number") == null) {
            if (!errorMsg.equals("")) {
                errorMsg += ", ";
            }
            errorMsg += "Credit Card #";
        }
    } else if ("CHECK".equals(data.getString("Payment Type Code"))
            && data.getDouble("total").doubleValue() > 0.0d) {
        if (data.getDate("Check Number") == null) {
            if (!errorMsg.equals("")) {
                errorMsg += ", ";
            }
            errorMsg += "Check Number";
        }
    }
}

if (!errorMsg.equals("")) {
    errorMsg = "You must enter the following fields in order to book this Order<p/>"
            + errorMsg;
}

Perform default value population before insert

if (condition) {
data.set("attributeToBeDefaulted", "Default Value");
}
Checking detail rows when the master row is inserted or updated
if ("ENTERED".equals(data.get("flowstatuscode")) && "B".equals(data.get("bookpricingflag"))) {
if (data.getDetailRows() != null && data.getDetailRows().size() > 0) {
throw new RAException("Pending Line Changes", "You must save the lines before booking the Order");
}
}
Record changes to a different data source
RPCModelData model = new RPCModelData();
model.set("Cust Account Id", data.get("Sold To Org Id"));
model.set("Context", "Order");
model.set("Type", operation == 'I'?"I": (operation == 'D'?"D":"U"));
model.set("Context Id", data.get("Header Id"));
model.set("Context Text", ((Double)data.get("Order Number")).longValue() + "");
if (operation == 'U') {
model.set("comments", db.getDiffHtml(data));
}
db.postObjectToDB("RecentActivities", model);

Sample code to implement mass soft delete based of the criteria provided by the user

Double requestId = data.get("requestId");
Double concRequestID = data.get("concRequestID");
Double createdBy = data.get("createdBy");
String statusCode = data.get("statusCode");

StringBuilder sb = new StringBuilder();
sb.append("UPDATE MY_TABLE SET STATUS_COE='D' WHERE STATUS_CODE <> 'D'");
List<Object> params = new ArrayList<Object>();
if (requestId != null && requestId.longValue() != -1) {
	sb.append(" AND REQUEST_ID = ?");
	params.add(requestId);
}
if (concRequestID != null) {
	sb.append(" AND CONC_REQUEST_ID = ?");
	params.add(concRequestID);
}
if (statusCode != null) {
	sb.append(" AND STATUS_CODE = ?");
	params.add(statusCode);
}
if (createdBy != null) {
	sb.append(" AND CREATED_BY = ?");
	params.add(createdBy);
}
if (params.size() == 0) {
	throw new RAException("Invalid Request", "You must filter the data before deleting!");
}
int count = db.executeUpdate(sb.toString(), params.toArray());
data.setParam("im", count + " rows deleted!"); // displays informational message to the user
skipDML = true; // skip the DML performed by the platform

Populate the request Id & file name of the excel sheet that is being uploaded by the user

data.set("Request Id", db.getSessionValue("uploadrequestid"));
data.set("File Name", db.getSessionValue("uploadfilename"));

Location

101 California Street, Suite 2710
San Francisco, CA 94111


440 N. Wolfe Rd.
Sunnyvale, CA 94085


Office 11, 5th Floor, Building 9,
Mindspace IT Park
Hyderabad 500081

p: +1 (844) AT CloudIO (844-282-5683)
f: +1 (650) 300-5247 | e: sales@cloudio.io
© 2009, 2017 CloudIO Inc. | Terms of Use | Privacy Policy