Developing Applications for Wolfram Enterprise Private Cloud:
Some examples, tips, and tricks

Arash Mahdian, Lin Guo, and Chad Knutson

Join the Conversation #WolframTechConf

Modern web application

Responsive, interactive, multiple functionality, fast

Examples:  Wolfram Cloud, web mail, facebook, online banking, ....

Approach

Use Wolfram Research technology for server-side (backend) evaluations and html + javascript for client-side (frontend) evaluations

WRI technologies

WolframCloud, Wolfram Enterprise Private Cloud

Wolfram Language built-in functions:  CloudDeploy, FormFunction, FormPage, APIFunction, Ask ...

Evaluations or responses can be complex, interactive, but they have a single functionality

$CloudBase="https://www.wolframcloud.com";
CloudConnect["chadk@wolfram.com"]

ca = CloudDeploy[
FormFunction["x"->"Number", 
Manipulate[Plot[Sqrt[#x x] Sin[a  x],{x,0,3 Pi}],{a,1,10}]&,
"HTMLCloudCDF"
],
"wtc2016/manipulate",Permissions->"Public"]

Example 1:  trivial web application

Single functionality, but extends on what is possible with WL forms ( a moving target!)

Architecture type 1

WEPC hosts both the web page, javascript file,  and the APIFunctions

CloudObject["wtc2016/wepcForm2.html"]

Deploy trivial web app

Backend

APIFunction to Plot a math expression

co=CloudDeploy[
APIFunction[{"input"->"MathExpression"},
<|"plot"->ExportString[ExportString[Plot[#input,{x,0,10}],"PNG"],"Base64"]|> &,
"JSON"
]
,
"wtc2016/simpleAPI"
,Permissions->"Public"
]

Note the output formatting used.  JSON object with the byte string of the image, so output is not human-readable

CloudObject["wtc2016/simpleAPI?input=sin(x)"]

Additional api:   verify the input to be plotted

c1 = CloudDeploy[
APIFunction[{"input" -> "String"},
Module[{inpint},
inpint = Interpreter["MathExpression"][#input];
If[Head[inpint]===Failure,
inpint = "Cannot parse your input";
];
   <|"image" -> ExportString[ExportString[TraditionalForm[inpint], "PNG"], "Base64"]|> 
]&,
 "JSON"
]
,
 "wtc2016/checkInps"
, Permissions -> "Public"
]

Frontend

HTML page

loads scripts and styles we need

defines components that will be populated by JS functions

fileh="C:\\Users\\chadk\\TechServices\\wepcForm2.html";
ch =  CloudObject["wtc2016/"<>FileNameTake[fileh]];
CopyFile[fileh, ch];
SetPermissions[ch, "Public"];
ch

Javascript code

api calls

event handlers

filej = "C:\\Users\\chadk\\TechServices\\checkInput.js";
cj =  CloudObject["wtc2016/"<>FileNameTake[filej]];
CopyFile[filej, cj];
SetPermissions[cj, "Public"];
cj

Additional notes

Authentication

Can require users to authenticate on WEPC

api calls must include authentication cookies

CreatePermissionsGroup["myApp",{"ling@wolfram.com","arashm@wolfram.com"}];
SetPermissions[CloudObject[MouseOver],PermissionsGroup["myApp"]->{"Read","Execute"}]

Data formats

JSON is a useful structure for passing data back and forth between frontend and WEPC apis

fapi = APIFunction["in"->"JSON",  
StringTemplate["Hello, `1` `2`.  You are `3` years old."][ Lookup[#in,"FirstName"] , Lookup[#in, "LastName"],Lookup[#in,"Age"]]&
];
input = ExportString[<|"FirstName"->"Rickey", "LastName"->"Henderson", "Age"->57|>,"JSON"]

fapi[<|"in"->input|>]

Error handling with JSON output

fap2 = APIFunction["in"->"JSON",
Module[{result, success="Success"},
result=
If[Lookup[#in,"Age"] < 0,
success="Failure";
"Age can't be negative"
,
StringTemplate["Hello, `1` `2`.  You are `3` years old."][ Lookup[#in,"FirstName"] , Lookup[#in, "LastName"],Lookup[#in,"Age"]]
];
<|"success"->success, "result"->result|>]&
,"JSON"];

fap2[<|"in"->input|>] // ExportString[#, "JSON"]&

fap2[<|"in"-> ExportString[<|"FirstName"->"Chad", "LastName"->"Knutson", "Age"->-3.5|>,"JSON"]|>] // ExportString[#,"JSON"]&

Example 2: yet another trivial web application

Data access and analysis

Architecture type 2

WEPC provides APIFunctions (Microservices)

Client view is built with web frontend technologies

A server in between client and WEPC-hosted APIs provides more options for user authentication, load balancing, etc.

Link

Back-end Considerations

MouseOver

CloudAccountData

Dataset[CloudAccountData["Products"]][1]

CloudLoggingData

Dataset@CloudLoggingData[]

Dataset@CloudLoggingData["Task","YearToDate"]

DateListPlot[CloudLoggingData["Task","YearToDate","CallRateTimeSeries"]]