BookmarkSubscribeRSS Feed

Selecting Different JES Web Application Outputs

Started ‎06-04-2021 by
Modified ‎06-04-2021 by
Views 7,452

In my previous article I demonstrated how to use the Job Execution Service Web Application to make a job request.  After the job completes running, its results are returned to the user interface in the form of an ODS HTML table.  One common question I get about creating applications using the Job Execution Service Web Application is if the job's results can be delivered in a different format.  The most popular request is if a JSON file can be returned.  Well, as it turns out it's very easy to do this!  As a matter of fact the Job Execution Service Web Application's documentation has a specific example which shows how to format a Job's results as a JSON file.


In this article, we will be building on the example I demonstrated in my previous article.  Specifically, we will add an additional prompt to the user interface asking the user if they would like to have the job's results returned as a JSON file or as a SAS ODS table.  If the user selects "JSON File" then we will use the concepts from the documentation's example to return the job's output as a JSON file.  After the JSON file is returned, some basic formatting will be applied to convert the JSON file's contents into a simple bulleted list.


The completed application will look like this:






This article will step you through how to build this example.  All code discussed is available in this GitHub Repository.


Let's get started!


Step 1: Conditionally changing what the Job's Source code returns


In order to edit the source code of our job, right click on the job and select "Edit" -> "Source Code":





The original example leveraged PROC REPORT to conditionally highlight the ODS table's cells depending on the state of the cas table.  For this example, we will keep it simple and only print the ODS table's output using PROC PRINT.  To do this simplification, all code beneath the step below can be removed:



/* run the getLoadedTables macro  */
data _NULL_;
	set reportCaslibs;
	call execute('%getLoadedTables(' || trim(caslibEndpoint) || ')');

The next thing to do is to create a reporting table sourced from the output dataset which applies some formatted labels to the variables.  The code to do this is below:


data getReportDataSourcesRPT;
set getReportDataSources;
reportCasLib = upcase(reportCasLib);
state = upcase(state);
label reportCasLib="Caslib" reportCasTable="Table" state="State";

Finally, we can produce the output based on what the user has selected (aka the value of the reserved macro variable - "_output_type").  To do this, we will simply add some conditional macro logic.  If the value received is "JSON", then PROC JSON is used with webout (as demonstrated in the example) to create a json file.  Alternatively, if the value is "ods_html5", then PROC PRINT is used to create an ODS HTML table.  The code to do this is below:


/* 		generate the appropriate output */
/* 		user selected JSON as output - return output as json file */
%if %qtrim("&_output_type") = "json" %then %do;
proc json out=_webout nosastags pretty;
  export getReportDataSourcesRPT;
run; quit;

/* 		user selected ODS as output - return output as SAS ODS Table */		
%if %qtrim("&_output_type") = "ods_html5" %then %do;
	proc print data=getReportDataSourcesRPT noobs label;
	label reportCasLib='CAS Library'
	reportCasTable='CAS Table'
	state='CAS Table State';


And that's it!  Our Job's source code is ready to dynamically create the output the user has requested!  Next we will need to work on our user interface to prompt the user to make a output type selection, and then if JSON is requested format the output to a bulleted list.


Step 2: Adding an additional prompt to the user interface and formatting the response


We will first need to prompt our users to see if they would like the job results returned as a JSON file or a SAS ODS Table.  To do this we will need to edit the HTML for our JOB.  This can be achieved by right-clicking on the job and selecting "Edit"->"HTML form": 





From here we can see the HTML code that we will be editing.  Directly above the <div id="reportList"> tag, place the following code:


</nbsp>Output Format:
<select name="outputFormat" class="jobexec_sample_select">

Additionally, it would be nice if the job's output was left justified.  To do this, change the two "center" tags that contain the "JobResults" div tag to "left".


The complete HTML form and "JobResults" div tag should now look like this:



Now that our HTML dropdown is in place, we need to make it functional by editing our javascript function that submits the form data.  We will now be including a value telling us what the user has selected for the outputFormat prompt.  Depending on what has been selected, we will be setting the value of the reserved macro variable "_OUTPUT_TYPE" to either "JSON" or "ODS_HTML5" (ODS_HTML5 is the default).  To do this, navigate to the javascript function named "submitForm" and directly underneath the 'formData.append('_csrf', "$CSRF$");' line, add the following lines:


if (document.querySelector('[name="outputFormat"]').value == "JSON") {
	formData.append("_output_type", "json");
} else {
	formData.append("_output_type", "ods_html5");


If the user has selected "SAS ODS Table" the Job will return a nicely formatted HTML table and place it in the "JobResults" div tag.  However, if the user selects JSON file, we probably want to display something nicer than just the JSON text.  To do this, we will use some basic javascript to convert the returned JSON file to something that is more visually pleasing.  To keep this article's example very simple, we will convert the JSON to a bulleted list.  To do this, we will add some logic to the javascript function that displays the job's results.  Navigate to this function and update the "request.onreadystatechange = function ()" block to include the following:


request.onreadystatechange = function () {
	if (this.readyState == 4) {
		if (this.status == 200) {

			if (document.querySelector('[name="outputFormat"]').value == "JSON") {

				var jsonResponse = JSON.parse(this.responseText)
				var i;
				var outputList = document.createElement('ul');
				for(i = 0; i < jsonResponse.length; i++) {		    	
					reportCaslib = "Caslib: "+jsonResponse[i]['reportCasLib']
					reportCasTable = " || Table: "+jsonResponse[i]['reportCasTable']+" || State: "
					reportCasTableState = ""+jsonResponse[i]['state'];
					var listItem = document.createElement("li");

			document.getElementById("JobResults").innerHTML = "<h1 class='jobexec_sample_name'>Report's Data Source(s) - JSON file (formatted with Javascript):</h1>" + outputList.innerHTML;
		} else {
			document.getElementById("JobResults").innerHTML = "<h1 class='jobexec_sample_name'>Report's Data Source(s) - SAS ODS Table:</h1>" + this.responseText;

		else {
			document.getElementById("JobResults").innerHTML = "Status: " + this.status;


Wow!  That's quite a change to the function!  Let's take a closer look at what it does. 


First, we check to see if the user has selected "JSON" for their output.  If they have, we begin by parsing the response and output it to the console (outputting the response to the console is not necessary but has been included in this article's example for educational purposes).  After this we create a new html "ul" element and store it in a variable named "outputList".  After this, we loop through the JSON's contents.  On each pass of the loop, we capture the iteration's reportCaslib, reportCasTable and reportCasTableState's value and save them to variables with some formatting around them.  After this, we simply create a new html "li" element and store it in a variable named "listItem".  With these pieces in place, we simply append the reportCaslib, reportCasTable and reportCasTableState's values to the listItem.  To complete our loop, we take the final listItem variable and append it to the outputList.  Finally, we can output the results to the "jobResults" div tag.  For a more pleasant viewing experience, we will prefix the output with a nice title explaining that the user is viewing the results of the job as a JSON file (formatted with Javascript).  


It should be stated that this javascript is very basic and there are much better ways of doing this formatting.  However, the purpose of this article is to show how to deliver different types of output in a Job Execution Service Web Application Job.  Hence the javascript in this example has been kept very elementary.


If the user has selected the SAS ODS Table option, the process is much simpler!  All we need to do is add our title prefix and output the results from the job.


Great!  We've converted our javascript function to process the JSON output (if that's what the user has selected) to a bulleted list.  As stated above, while this example is very basic, it could easily be improved upon.  For example, if the cas table's state is "UNLOADED", additional logic could be added (to both the javascript function as well as the SAS ODS table) to color the output text red.  


And that's it, our HTML and Javascript is ready!  All that's left is for us to do some window dressing.  Let's change the title in our HTML to reflect what our app will do.  I decided to change the title to "This Example JES Web Application Job will Display Details About a VA Report’s Data Source(s) in different formats", but you can use any title you'd like!  Secondly, you might have noticed that we used the "jobexec_sample_select" class in our output type selection.  We should keep this consistent with our second report prompt.  Additionally, since we have some text in front of our output type prompt, we should also have some text in front of our second prompt.  To do both of these tasks locate the variable "prompt" within the createSelection javascript function and replace it with:


var prompt = 'Select Report:  <select name="reportSelect"  class="jobexec_sample_select">';


And that's it!  We have successfully added the needed components to first prompt the user to select their output format, and then return the appropriate results. By leveraging both the Job's source code as well as the HTML prompt we can really begin to shape our app to create any type of output we want:


*The code in this article is intended to be run against VA reports which have been developed using the Visual Analytics interface using loaded CAS data sets as the data source(s). Results might vary when selecting preinstalled VA reports, VA reports created via other methods or VA reports that have no data sources associated with them.

How to make this example work for you


On GitHub, you will find all the code discussed in this article.  All code is intended to be saved in a SAS® Job Execution Web Application 2.2 job definition within a Viya 3.5 environment. 


On Github, you will find the following support files for this article:

  • A JSON file containing the completed JES Job - JES_selectOutputFormat.json
    • *A SAS Administrator can import this to the Viya content folder "/Public" within a SAS Viya 3.5 (or later) environment using these instructions
  • The JES job's source code that makes the API requests, runs the CAS actions and Viya Procedure and displays the ODS output -
  • The JES job's HTML code to create prompts and execute the job - JES_selectOutputFormat.html

 Take Me to GitHub!



Version history
Last update:
‎06-04-2021 03:10 PM
Updated by:



Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.

If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website. 

Register now!

Free course: Data Literacy Essentials

Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning  and boost your career prospects.

Get Started

Article Tags