X

The Visual Builder Cloud Service Blog

Recent Posts

Oracle Visual Builder Cloud Service

Announcing The Visual Builder Cookbook

The Visual Builder team is excited to announce the release of the new Visual Builder Cookbook - a key educational resource that will help you implement a variety of techniques with Visual Builder. The cookbook provides a collection of step-by-step recipes that teach you how to implement common usecases with Visual Builder. Not only do you get the instructions, you also get the full code for all the solutions - so you can further inspect and learn from it. The cookbook is provided as a Visual Builder application hosted at - https://vbcookbook.oracle.com. Furthermore, you can create your own copy of the application on your server. Simply create a new application and choose the "Oracle Visual Builder Cookbook" template for the app - this will install a complete copy of the cookbook in your environment. The app has everything you need to run the samples - including the backend business objects - and the code for all the samples is right there at your fingertips. What's In The Cookbook? The book cover recipes that address the following topics: Handling master-detail and many-to-many relationships Working with tables and lists and implementing - filtering, custom styling, row actions, multi selection Editable table and saving data in transaction/batch List of values (LOV) patterns Multi step wizard File upload Working with data in Oracle Databases using ORDS And much more Using the Cookbook We suggest you review the various solutions demonstrated in the cookbook, for each one you'll see a page that demonstrate the functionality. Next to the sample app on the same page you'll find step-by-step instructions on how you can build the same functionality using the Visual Builder designer.  If you created a cookbook application in your own VB instance - you'll also be able to directly access the code, look at the variables, action chains, and any other artifact involved. Got questions? The team behind the cookbook - Sumedh Chakravorty, Umang Goyal, Vinay Agarwal, Walter Egan, John Ceccarelli and David Konecny - are looking for your feedback, and will be happy to help with any further questions on the samples - post them on the VB community forum. 

The Visual Builder team is excited to announce the release of the new Visual Builder Cookbook - a key educational resource that will help you implement a variety of techniques with Visual Builder....

Visual Builder Studio

Automating Deployment to WebLogic on Oracle Cloud Infrastructure

We are seeing many of our customers transitioning their workload to Oracle Cloud Infrastructure including Enterprise Java applications that are being deployed there - many on the WebLogic for Cloud Infrastructure solution. In the blog below we show an approach to automate continuous delivery onto servers running on OCI. In the video below we are using a JSF project and go through the full flow of code change lifecycle with Visual Builder Studio including: Git version management Security check for vulnerabilities in 3rd party libraries  Packaging the app Automating deployment Deploy To OCI VMs To deploy artifacts on VMs running in Oracle Compute, we establish SSH connectivity to our OCI compute instance. This is done in a pre-build step in the Job definition - provide the private and public keys used (and a passphrase if the key require it). Then we use shell scripts to do the deployment.   In the demo I use an SCP command to copy the war file generated by the package job to the compute instance. Then I use the WebLogic wlst utility to deploy this war file to the running instance. I point the /u01/middleware/oracle_common/common/bin/wlst.sh to a file that has the following steps: connect('user','password','t3://localhost:7001') cd ('Servers') deploy(appName='JSFWebApp', path='/home/opc/Downloads/simple-jsf-example.war') exit() While the demo above show the deployment to WebLogic, you can use a similar technique to deploy other types of loads to other servers running on compute.

We are seeing many of our customers transitioning their workload to Oracle Cloud Infrastructure including Enterprise Java applications that are being deployed there - many on the WebLogic for Cloud...

Oracle Visual Builder Cloud Service

Improved Windowing and Navigation in Visual Builder Studio

The new Redwood-based design time environment for visual applications in Visual Builder Studio doesn't just look nicer, it also streamlines your work as a developer. Here are some tips that will help you leverage the new environment.  New Visual Editor Layout All the building blocks that make up a visual application page - such as variables, actions, events, etc - are easily accessible from a new tab bar at the top of the editor. In addition this tab shows a count of artifacts in each category, and highlight any areas where the auditing system identified errors or missing things - highlighting them with a red underline. . New Windowing Layout You can easily collapse and expand the windows in your environment by clicking on them. This helps get more editing space for the visual editor and to hide windows that are not relevant to your current work.   You'll also notice that the component palette and the structure pane now occupy the same space. Note however that you can still drag and drop UI components from the component palette to the structure window - start dragging a component and you'll see the structure window becoming active. Context Aware Operations Visual Builder Studio streamlines your development further by providing easier access to operations in specific context. For example, when you create an action chain and drop an action to call a JavaScript module - you can create the JS module directly from the action's property inspector. Further more, you can directly navigate to that function from the same location. Note how the live audit highlights missing things in actions settings - for example if an assignment is missing in an assign variable action, or a JS function in a call JS module action. These new features and many other "small" enhancements result in a smoother development experience that we hope you'll enjoy and benefit from.

The new Redwood-based design time environment for visual applications in Visual Builder Studio doesn't just look nicer, it also streamlines your work as a developer. Here are some tips that will help...

Moving Visual Builder Apps to Visual Builder Studio

If you currently develop applications with Visual Builder we hope you already saw the news about the new Oracle Visual Builder Studio offering. This new service adds a complete environment that helps manage VB apps development across team members, and can automate continuous integration and continuous deployment of VB apps. If you haven't read about this - here is a quick blog summary of the advantages VB Studio offers for VB developers - and here is a short video showing the day-to-day experience working with VB Studio and VB apps. So how do you take your existing apps and bring them to this new environment? It's quite simple - you export the app from your Visual Builder instance - and then import the code into a new project in Visual Builder Studio. The following video shows the steps you need to take to get your app into Visual Builder Studio. As you can see, when you bring in your app, we load it into a Git repository in your project - this is now the source of truth for your application's code. The workspace you create is your own "local copy" of the code that is for your use only. The workspace can map to different branches of the app, and once you are done working on this copy you push the changes to the branch in the git repo - so others can access them. The life cycle of your application also changes - no longer will you be using the stage and publish menu - you'll be using the VB Studio build jobs to package and deploy your app. As you can see in the video the deployment pipeline is created for you automatically when you import your app - but feel free to adjust it, or add additional deployment pipelines or steps. Now that your code is in Visual Builder Studio you can start leveraging the advanced Git support, as well as the integration with the issue tracking system and agile project management feature of VB Studio. P.S. - If your application uses Business Objects - you'll also want to automate the lifecycle of the BO data as shown in this blog.  

If you currently develop applications with Visual Builder we hope you already saw the news about the new Oracle Visual Builder Studio offering. This new service adds a complete environment that helps...

Oracle Visual Builder Cloud Service

Connecting to an API Gateway endpoint from Visual Builder

In the previous blog, we discussed calling an Oracle Function from VB.  In this post, we accomplish the same task using the OCI API Gateway acting as a point of entry to the Function.  The API Gateway provides a single point of entry to the services in your organization, and helps in consolidating common tasks such as request/response transformations, CORS support, request limiting etc We will build upon resources used in the previous blog so you are recommended to complete that before you proceed. We will use a python based OCI function from the sample OCI functions in github.  This Function lists the compartments available in the tenancy.  Since this function also calls other OCI Resources (ListCompartments), we will need to place this Function in a Dynamic Group.  This would be an addition to what we did in the hello-java function in the previous blog Setup the OCI Function Creating the oci-list-compartments-python Function Repeat the section of Create the hello-java function in the previous blog with the following differences: Instead of the hello-java function, use the oci-list-compartments-python After doing the fn init and going into the function directory, overwrite the function files from the github samples  wget https://raw.githubusercontent.com/oracle/oracle-functions-samples/master/samples/oci-list-compartments-python/func.py wget https://raw.githubusercontent.com/oracle/oracle-functions-samples/master/samples/oci-list-compartments-python/func.yaml wget https://raw.githubusercontent.com/oracle/oracle-functions-samples/master/samples/oci-list-compartments-python/requirements.txt When you invoke the function using fn invoke, you would get an error as below Error invoking function. status: 502 message: function failed. This is because our Function is now calling OCI Resources.  We will add the necessary configuration in the next section in order for the Function to be able to access other resources.   Adding OCI Resource access to Function For the Function to be able to access OCI Resources, we need to make sure it is within a Dynamic Group. Navigate to Dynamic Groups from Identity -> Dynamic Groups or via quick search, and begin creating a Dynamic Group.  Give a relevant name (e.g. FunctionsInVBAPP).  Add a rule expression that will select all the relevant functions and click Create.  In my case, I have selected all functions that belong to the oci-fn-vb compartment with the below rule ALL {resource.type = 'fnfunc', resource.compartment.id = ' ocid1.compartment.oc1..aaaaaaaaxyz'} where the resource.compartment.id has the OCID of the oci-fn-vb compartment Note : The ListCompartments API doesnt require a special Policy to gain access.  But for other kinds of actions, like ListVCNs, you might have to add an IAM Policy that will give this group access to the relevant API (see the help documentation for more on this) Once you have created the Dynamic Group for the Function, try to invoke the function again from CloudShell - this should now return a list of compartments fn invoke oci-fn-vb-app oci-list-compartments-python {"compartments": [["ocid1.compartment.oc1..aaaaaaaaf...abc", "firstcompartment"], ["ocid1.compartment.oc1..aaaaaaaaf...def", "ManagedCompartmentForPaaS"], ["ocid1.compartment.oc1..aaaaaaaao...efa", "oci-fn-vb"], ["ocid1.compartment.oc1..aaaaaaaaf...ghi", "oci-test"]]} Setup an API Gateway to the OCI Function Let us now create and configure an API Gateway to connect to the Function Create an API Gateway Navigate to Developer Services -> API Gateway.  Select the oci-fn-vb Compartment, and start creating a Public API Gateway.  Select the VCN and public subnet  that was created in the previous blog.  This has the necessary routing to the Internet Gateway too.   After the API Gateway is created, we need to configure a backend that would route to our Function oci-list-compartments-python.   We add backends and routes via Deployments. Click on the newly created API Gateway oci-fn-vb-apigw, navigate to Deployments and click on Create Deployments.  Choose the "From Scratch" option and enter a relevant name and /v1 as the path prefix.  For now we wont configure any authentication or CORS, so leave the other options as-is. Click Next and configure the Route.  Give the following details : Path : /compartment Methods : GET Type : Oracle Functions Application : oci-fn-vb-app Function : oci-list-compartments-python Click Next and review the information provided and create the deployment.  After creation, note down the endpoint for the Deployments.  The format would be something like below: https://plbo2fabcigu.apigateway.ap-mumbai-1.oci.customer-oci.com/v1 Therefore full URL to the compartment resource would be  https://plbo2fabcigu.apigateway.ap-mumbai-1.oci.customer-oci.com/v1/compartment Setting up the Ingress rule for API Gateway If you try to connect to the compartment Resouce URL that we got in the previous section via browser or any API client like Postman, it is likely that you will get a timeout.  This is because the public subnet is not accepting HTTPS traffic.  Since we had created the VCN via the VCN Wizard, we already have the route tables and Internet Gateway correctly configured.  There is one more step we need to complete for the subnet to accept HTTPS traffic, which is defining an HTTPS ingress rule for our subnet. Navigate to Networking -> Virtual Cloud Networks and select the VCN (In my case, it is oci-fn-vb-VCN)  Click on the VCN, this should show both the public and private subnets.   Click on the public subnet.  This should show you the Security Lists of the public subnet. Clicking on the security list would show you all the Ingress Rules.  Proceed to add an Ingress Rule for HTTPS as below Description : HTTPS ingress rule Source CIDR : 0.0.0.0/0 IP Protocol : TCP Source Port Range : All (Default) Destination Port Range : 443 If now you try to connect to the resource URL, it should be connectable now, but it will likely give an error like below : {"message":"Internal Server Error","code":500} This requires the API Gateway be configured with adequate permissions to call the required Function, which we will see in the next section Configuring the API Gateway to call the oci-fn-vb-app functions Go to Identity -> Policies.  Create a Policy that allows API Gateway to execute all Functions in the oci-fn-vb compartment E.g. ALLOW any-user to use functions-family in compartment   where  ALL { request.principal.type= 'ApiGateway' ,        request.resource.compartment.id = ''  } Now connecting to resource URL https://plbo2fabcigu.apigateway.ap-mumbai-1.oci.customer-oci.com/v1/compartment will work and give you the list of compartments {"compartments": [["ocid1.compartment.oc1..aaaaaaaaf...abc", "firstcompartment"], ["ocid1.compartment.oc1..aaaaaaaaf...def", "ManagedCompartmentForPaaS"], ["ocid1.compartment.oc1..aaaaaaaao...efa", "oci-fn-vb"], ["ocid1.compartment.oc1..aaaaaaaaf...ghi", "oci-test"]]} Setting up Service Connection in Visual Builder to API Gateway Create Service Connection by Endpoint to compartment resource Login to Visual Builder.  Create a Visual Application OCIServiceTest.  In this, navigate to Service Connections and proceed to create a new Service Connection.  Choose the Define by Endpoint category when prompted to select Source In the Service Connection Wizard, choose as below : Method : GET URL : API Gateway Deployment Endpoint full path ( e.g. https://plbo2fabcigu.apigateway.ap-mumbai-1.oci.customer-oci.com/v1/compartment) Action Hint : Get Many Click Next.  Choose a relevant Service name and title.  In my case the service is called ociCompartments. Navigate to the Servers tab.  Since we have not specified any authentication to the API Gateway deployment, we can choose to have no authentication.  However since we also didnt configure any CORS support, we would need to set Connection Type as "Dynamic doesnt support CORS" (More on Connection Types here ) Next, navigate to the Test tab and test the Service Connection.  It should give you a status code of 200 OK and a valid response Finally create the Service Connection.  Now this can be added to web and mobile apps for retrieving data. Conclusion We covered the aspects of connecting to a Function exposed via the API Gateway.  There are still some improvements that can be made, namely Authentication and CORS support.  We will see how to tackle this in the next blog  

In the previous blog, we discussed calling an Oracle Function from VB.  In this post, we accomplish the same task using the OCI API Gateway acting as a point of entry to the Function.  The API...

Oracle Visual Builder Cloud Service

Adding Pull to Refresh Behavior in Mobile Apps

Pull to Refresh is a common touch interaction pattern in mobile apps where by placing your finger on the device and dragging down you get an updated set of data onto your device. In this blog we show how to add this user interaction to your mobile Visual Builder app using a component from the Visual Builder component exchange. The component exchange in Visual Builder contains various components that you can add to your development environment and apps. To add a component simply click the "Get Component" in the component palette, find the component your are after and choose "Install". The component will be added to your visual editor's component palette. In the demo below we are adding a "Pull to Refresh" component - this is a component that implement the user interaction. Inside the component, you place other UI component that you want to refresh. In our example we place a listView component into the default container of the pull to refresh component. The component exposes an ojRefresh event, which we use to hook an action chain to. In the action chain we can execute the logic that will implement the refresh. In the demo we simply use the fire data provider event of type refresh on the ServiceDataProvider that populates our list component.  We then notify the component that we are done with the refresh, which we do by calling the component method for refreshComplete. (Make sure your pull to refresh component has an ID property set, to be able to pick it up in the action properties). The last step is to set the list, the pull to refresh component, and the parent component height to 100% through the style attribute. This helps VB distinguish between a scroll event and a pull to refresh event on the list component. Here's an end to end demo:

Pull to Refresh is a common touch interaction pattern in mobile apps where by placing your finger on the device and dragging down you get an updated set of data onto your device. In this blog we show...

Managing Business Objects Lifecycle with Visual Builder Studio

With Visual Builder Studio the lifecycle of the application's code is managed separately from that of data that is stored in business objects. In this blog we'll show you how to hook up data management into the process that deploys your application. Managing the data lifecycle can be done using the new Visual Application build steps that were added to Visual Builder Studio. Note that this demo is a continuation of the previous blog that shows the initial configuration of a package and deploy steps. The data manager in Visual Builder helps you get data in and out of business objects while developing the app. We'll use the Visual Builder Data Manager "Export all Data" option to generate a zip file with base data we can use in our dev/test app. This will create a zip file with csv files with the data for each business object. In Visual Builder Studio, we create a separate Git repository to store this file, as it is not part of your application code. Then we are going to load the exported file into that repository.  To automate populating business objects we create a new build job that uses the Import Data step from the Visual Application category. Note that the application we are importing into in the video is published with a version in the path ("Include the application version in the URL" is checked) - which means this is not a "live" app as the URL will change when we modify the app version. We can therefor import data into it directly. Applications that don't have the "Include the application version in the URL" checked are your "live/production" apps - with a fixed URL that won't change when you deploy new versions. If you want to do a similar import of data into a live/production app, then you need to first use the Lock step to lock the app, then import the data, and then Unlock the app. Note that the options also include an Export Data - which you can use to first export data from the current instance of the app, then do the deploy step, and then import the data back in. Here are the base steps:

With Visual Builder Studio the lifecycle of the application's code is managed separately from that of data that is stored in business objects. In this blog we'll show you how to hook up...

Oracle Visual Builder Cloud Service

Connecting to Oracle Functions from Visual Builder

Oracle Functions, the serverless offering from Oracle Cloud Infrastructure is an excellent way to run your code without worrying about the underlying infrastructure, and also helps to optimize your costs as you only pay per invocation of the Function. In the previous blog, we connected to an OCI REST API using the OCI Signature authentication.  In this blog we go a step further and invoke a simple Hello World OCI Function from a VB application Setting up the OCI Function Login to the OCI console for your tenancy.  Make sure the user that you are logging with has the relevant permissions to create Functions, VCNs, repositories etc. via IAM Policies (This can be accomplished using groups and policies ).  In my case I am logging via a user who is in the OCI Administrators group which has access to manage all resources.     Tip : Within the OCI console, you can click the Hamburger menu and navigate through various offerings, or you could use the search to quickly get to the thing you are interested in. Create a Compartment First, we will create a Compartment where our Function and related resources will live.  A Compartment can be thought of a logical grouping of OCI resources, to which you can grant access to various users (or other principals).   We navigate to the Compartment via search or via the hamburger menu ( Identity -> Compartments ).  Here we will create a new compartment called oci-fn-vb - this will be the place where we will create all our OCI resources.  Note down the OCID of the compartment for future use. Create a Virtual Cloud Network (VCN) A VCN is necessary for the Function to communicate with the outside world.  Navigate to Virtual Cloud Networks via search or via the hamburger menu (Networking -> Virtual Cloud Networks).  You can choose the "Start VCN Wizard" for quickly creating the right configuration of VCNs that also has Internet Connectivity.  Uncheck the "Use the DNS Hostnames" option and let all the other values remain default (Note - the wizard also creates a private subnet and a NAT gateway, that we wont be using in this tutorial)   Here is how the VCN looks after the creation. We will be creating our Function resources in the public Subnet of this VCN. Create a repository OCI Functions are stored as Docker Images and hence need a Docker repository to be created within the OCI Registry (OCIR).  To create a new repository you can go to Developer Services -> Registry and create a new repository and note its name.  In this tutorial, I use a repository called oci-fn-repository This repository would be used when using the Quick Start for the function. Create an Application for the Function  We will first create an Application to add the function to.  Navigate to Developer Services -> Functions from the hamburger menu (or use the quick search).  Proceed to create an Application choosing the oci-fn-vb compartment (for both the VCN and the subnet) and keep the other stuff default.  The Application in my case is called oci-fn-vb-app   Create the hello-java Function Now open the newly created oci-fn-vb-app and click on the Getting started link available.  This will guide you through all the steps of creating a helloworld boilerplate java function via the OCI Cloud Shell and deploying it.  You would be using the repository already created to push the function image to.  At the last step you should be able to invoke hello-java function successfully from CloudShell. Tip : There are other Quick start samples for Oracle Functions on GitHub.  You can follow the instructions in the given README to install these Functions If we now check the OCI console for oci-fn-vb-app (remember to select the compartment you created it in) and navigate to Functions, we can now see the deployed hello-java Function Note down the Invoke endpoint of the hello-java function, as this is what we will be using to call the Function from VB.  It will be of the following format https://7imgabcd.ap-mumbai-1.functions.oci.oraclecloud.com/20181201/functions/ocid1.fnfunc.oc1.ap-mumbai-1.aaaaaaaaaby.xsysd....zxs5qq/actions/invoke   Obtaining the Credentials from OCI We have already covered this part in the "Getting OCI Credentials section" of the previous blog about OCI Signature authentication. Basically we need a key ID and a unencrypted private key to use in VB. Setting up the Service Connection in VB to call hello-java Function Create the Service Connection Login to Visual Builder.  Create a Visual Application OCIFunctionTest .  In this, navigate to Service Connections and proceed to create a Service Connection.  Choose the Define by Endpoint category when prompted to select Source In the Service Connection Wizard, choose as below : Method : POST URL : the Function invoke endpoint that we copied earlier (e.g. https://7imgabcd.ap-mumbai-1.functions.oci.oraclecloud.com/20181201/functions/ocid1.fnfunc.oc1.ap-mumbai-1.aaaaaaaaaby.xsysd....zxs5qq/actions/invoke) Action Hint : Create   In the next screen, the service name/id has been automatically populated.  Change this to be a meaningful value.  In my example the service is called ociFunction Add key ID and private key to the Service Connection Credentials Navigate to the Server tab to specify the authentication details.   Choose Authentication to be Oracle Cloud Infrastructure API Signature 1.0.  This is the API Signatures algorithm mentioned here.  Note that the Service Connection will always go via the proxy irrespective of what is chosen in the Connection Type attribute, due to the nature of the OCI Signature authentication. Click on the pencil icon next to the API Key.  There would be a place holder to put in the API Key as well as the Private Key.  Use the entire part of the Private Key including the BEGIN PRIVATE KEY till END PRIVATE KEY.  Save the credentials.   Add the request body In this case the hello-java accepts text/plain mime type, change the Media Type to be "text/plain", and give a sample request text.   Test and create the Service Connection After this, test the endpoint connectivity by navigating to the Test Tab.  Change the request type to text/plain and give a sample request text if not already so.  Click Send to obtain the response.  You should get a 200 OK response with the output of the Function as below.   Finally, create the Service Connection. That completes the setup of service connection from VB to an OCI Function.  You can now wire up this newly created Service Connection to webapps or mobile apps.    

Oracle Functions, the serverless offering from Oracle Cloud Infrastructure is an excellent way to run your code without worrying about the underlying infrastructure, and also helps to optimize your...

Oracle Visual Builder Cloud Service

Automate Visual Application's CI/CD with Visual Builder Studio

Oracle Visual Builder Studio offers an improved experience for packaging and deploying Visual Applications. We now offer declarative built-in tasks that let you package and optimize your app, deploy it (either stage or live version), and manage the data stored in the app. These declarative tasks are based on an updated set of Grunt tasks available for Visual Builder, which can also be leveraged in other CI/CD platforms. One of the nice features of Visual Builder Studio is that it automatically creates a CI/CD pipeline for your app when you create a workspace for a new or imported app. In this blog we explain what is actually being created, so you can implement additional CI/CD flows either in VBStudio or outside. Packaging the App The first build step we use is the package option for Visual Application - this step processes the code from your git repository, and creates zip files that contain an optimized version of your app ready to be deployed. Under the hood we are using the vb-process-local grunt task to achieve this. We then archive the resulting artifact so they can be picked up by the next build step - the deploy step. Deploying the App The deploy build job uses an Oracle Deployment step, that works together with the environments defined in your VBStudio project, to pick up the optimized app and deploy it to a target Visual Builder server. You'll see that this step allow you to specify whether the app should be in stage or publish/live mode, and indicate if you want a new database schema or to keep the existing data in the business objects used. This steps uses the vb-deploy grunt task to deploy the artifacts created before. Once the jobs are in place you can streamline their execution by including them as part of a pipeline: Using Grunt Directly In the video I'm also showing how you can use the same grunt tasks as part of a shell script to do deployment. You can use this approach if you want to package and deploy directly from your machine, or from external CI/CD systems. The script used is: npm install grunt vb-archive:sources --sources-zip-path=build/sources.zip vb-process-local vb-package vb-archive:optimized --optimized-zip-path=build/built-assets.zip grunt vb-deploy --url=https://yourserver/ic/builder/ --username=youruser --password=$pass To learn more about the grunt tasks Visual Builder provides, see our grunt tasks doc. Here is a demo of the end-to-end flow: Once your app is deployed, you might need to load data into the business objects that it uses - which are going to be empty initially. You can learn more about doing this with the import data build tasks described in this blog.

Oracle Visual Builder Studio offers an improved experience for packaging and deploying Visual Applications. We now offer declarative built-in tasks that let you package and optimize your app, deploy...

Oracle Visual Builder Cloud Service

Using OCI API signature authentication from Visual Builder

In this blog post, we will explore the OCI Signature authentication to call an Oracle Cloud Infrastructure REST API.  For this purpose, we will be using a simple GET API called ListInstances which returns a list of compute instances in a particular compartment. Visual Builder (19.4.3 onwards) supports signing requests via Oracle Cloud Infrastructure API Signature version 1 authentication method ( More details can be found here) . For this we require two parts: A Key ID which comprises of the Tenancy OCID, the User OCID and the fingerprint of a valid public key uploaded to OCI An unencrypted version of the private key in PEM format corresponding to the public key Obtaining the credentials from OCI Login to the OCI console for your tenancy. You can login with a user who is in a group that has been granted relevant privileges to list instances via IAM Policies (See the literature for more information about OCI users, groups and IAM policies).  In this example, I am logging as a user who is in the OCI Administrators group which has access to manage all resources. Obtain the OCI Key ID For this, we will note the Tenancy and the User OCIDs from the user's profile Tenancy OCID - From the Profile, click on the Tenancy displayed and copy the OCID from the resulting page User OCID - From the Profile, click on User Settings, and note the User OCID   Next we create a public and private API key pair.  We will create a private key locally (i.e. on our computer) by using openssl utility (note: you need openssl with version 1.0.1 or higher )  openssl genrsa -out oci-fn-vb-privkeyenc.pem -aes128 2048 Enter/Re-enter a passphrase when prompted to encrypt the private key and note the passphrase for future use This file oci-fn-vb-privkeyenc.pem is your encrypted private key.  Now we will generate the corresponding public key for uploading to OCI openssl rsa -pubout -in oci-fn-vb-privkeyenc.pem -out oci-fn-vb-pubkey.pem Enter the correct passphrase when prompted. Upload the public key to the OCI Console by navigating to User Settings -> API Key -> Add Public Key.  Choose the file oci-fn-vb-pubkey.pem .   This should get uploaded and also generate a fingerprint for this particular key as shown below.  Keep a note of the fingerprint. Construct the key ID by using the following syntax  key ID = [TENANCY OCID]/[USER OCID]/[KEY FINGERPRINT] As an example  ocid1.tenancy.oc1..aaaaxyz/ocid1.user.oc1..aaaaabc/1f:9a:f9:ad:4a:a4:44:6c:65:0e:94:4f:30:7c:91:ac We have the first part i.e. the key ID. Obtain the private key to use in Visual Builder If you open the oci-fn-vb-privkeyenc.pem file, you will see the following lines in your file. -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,E76204F69772B5958468790EEE41C8D5 dmQhVR08dVjd91ldj2q+2ASMd3tSLG0rfYl27hUSsjujK+FEJ7+4Jj+ozgif2LKf GF1EYyLO45FLW4r0lnH6pMrlMuLp5Dr1OWXEMVSRR6swaQG1dFPDZ9kVzDQkF4aQ 6bVeMpbW2jEsi6+V/0oQtLg7UdzrHnsKxRuo6326OKafzw5ICyCNL57w8yMwtl5i fo4vBCYktcf2Gyv/S154YSRXNAaIXt+P3pbkxJmpU73kZF4Q2KBxazEmi2FJM4F0 KU+5OkStQQ91/z0eUvv0c6L5cKMx1jDBUfyoGdqnQ4zlfVYWzouS2KEjUOCqeICp iGwcw57vOh+aHYqxnwTJRm3rMV7/nbjfIuJee5TCdD6Q5bazXxyLdeq3ER8wv1Q9 ............... -----END RSA PRIVATE KEY----- This indicates this is an RSA encrypted key.  We need to convert this into a PEM unencrypted key to be uploaded to VB openssl pkcs8 -topk8 -in oci-fn-vb-privkeyenc.pem -out oci-fn-vb-privkey.pem -nocrypt Now we will use the key ID and the oci-fn-vb-privkey.pem in the Service Connection Obtain the Compartment OCID Another thing we need to list instances is the CompartmentId, which is the OCID of the compartment for which we need to fetch the compute instances.  Navigate to Identity -> Compartments.  Find out the compartment you are interested in and note down its OCID.  We will be fetching the instances belonging to a compartment called oci-test which is nested within the root compartment   Setting up Service Connection in Visual Builder with OCI Authentication Create Service Connection by Endpoint to OCI API Login to Visual Builder.  Create a Visual Application OCIServiceTest.  In this, navigate to Service Connections and proceed to create a new Service Connection.  Choose the Define by Endpoint category when prompted to select Source In the Service Connection Wizard, choose as below : Method : GET URL : https://[OCI Regional host]/[version]/instances (e.g. https://iaas.ap-mumbai-1.oraclecloud.com/20160918/instances) Action Hint : Get Many In the next screen, the service name/id has been automatically populated.  Change this to be a meaningful value.  In my example the service is called ociListInstances1 Add key ID and private key to the Service Connection Credentials Navigate to the Server tab.  This holds all the configuration needed to connect to this endpoint.   Choose Authentication to be Oracle Cloud Infrastructure API Signature 1.0.  This uses API Signature algorithm mentioned here  The Connection Type field, which is used to control the use of a Proxy or Direct call, is immaterial here.  No matter what connection type you choose, the OCI Signature algorithm is such that it needs a server side proxy to be computed, and hence all requests to this Service Connection would go via Proxy. Click on the pencil icon next to the API Key.  There would be a place holder to put in the API Key (the Key ID) as well as the Private Key.  Use the entire part of the Private Key including the BEGIN PRIVATE KEY till END PRIVATE KEY.  Save the credentials Add the request parameter Since compartmentId is one of the mandatory parameters of ListInstances, we add it in Request -> Parameters tab in the section Dynamic Query parameters.     Test and create the Service Connection Next, test the endpoint connectivity by navigating to the Test Tab.  Give the OCID of the compartment in the compartmentId URL parameter, and click Send You should get a 200 OK response with a list of instances available in the compartment.  Finally, click on the create button to create the Service Connection. That completes the setup of service connection from VB to an OCI REST API.  You can now leverage this via a VB webapp or a mobile app.  

In this blog post, we will explore the OCI Signature authentication to call an Oracle Cloud Infrastructure REST API.  For this purpose, we will be using a simple GET API called ListInstances which retu...

Visual Builder Studio

Using GitLFS for Git Binary File Management with Visual Builder Studio

As a best practice your Git repository shouldn't include large binary files - since you usually don't actually manage the content of these files in a similar way to source code files. But sometime these files are part of your code base, and you would like to track them along with the rest of your code. GitLFS - an open source project - helps in doing this in an efficient way. The latest version of Oracle Visual Builder Studio added support for using GitLFS. Git Large File Storage (LFS) replaces large files such as audio samples, videos, datasets, and graphics with text pointers inside Git, while storing the file contents on a remote server. Visual Builder Studio will store the files in your Oracle Cloud Object Storage. In the demo below you can see how easy it is to use GitLFS with your free Git repositories in Visual Builder Studio. After you download and install GitLFS on your client, you can add it to a specific Git repo by issuing a "git lfs install" in the directory into which you cloned your repository. Then indicate which files to track using commands such as "git lfs track *.bin". Add the new .gitattributes file to your git transaction, and that's it. From now on, when you add files of the specific type to your git repo - they will be stored outside of your git repo. Here is a quick demo -  For more info see our doc.  

As a best practice your Git repository shouldn't include large binary files - since you usually don't actually manage the content of these files in a similar way to source code files. But...

Oracle Visual Builder Cloud Service

Embedding Visual Builder Apps In Oracle Cloud Applications

In some cases you will want to access Oracle Visual Builder application through an interface built with another product/service. For example, embed the VB app in a portal or another app. Embedding Visual Builder UI in an Oracle Cloud Application (Oracle's SaaS) page is another example of this use case. In this blog we'll show how to achieve this. Adapting the Visual Builder App There are three things you'll likely want to setup in your Visual Builder app when you know it is going to be embedded. The first one is a must do - in the web app settings->security section you should allow your application to be embedded in other servers. If not set, when a site will try to embed the URL of your app it will be denied and in the console you'll see a message similar to "Refused to display 'URL' in a frame because it set 'X-Frame-Options'". By default VB apps are not allowing other sites to embed them because of security concerns, so you need to specifically set this entry. (Note that you must re-publish your app after you change this setting). The other thing you likely want to do is remove any surrounding chrome around the core content of your app. These parts are usually defined in the shell page which acts as the template for your page. Simply go and edit the HTML removing things that are not needed in the embedded version. A third thing you can do is set variables in your app to accept input through the URL. This will allow the surroudning app to pass information to your VB app in an easy way. Simply mark a VB variable as "Input Parameter" and check the "pass on URL" box. Configuring The Oracle Cloud Apps Side For integration into Oracle Cloud Applications, you can use the ability to customize pages in the app using the Page Composer functionality. In the video you can see that I work in a sandbox - which you should create if you are doing any changes to the app. Make sure your sandbox enables the page composer functionality. When you are in a page you want to customize you can click to edit the page choose the area where you want to include the Visual Builder UI (a bit of understanding of ADF layout components helps to figure out where to add your section). Then you simply add a component of Web Page type (which is adding an iframe into your page). Then you can configure the URL that would be invoked. One nice thing you can do is add parameters that you pass to your VB app whose values come from other items on the page. In the video we are passing a parameter to a VB app on the URL - and then use that value to filter which records are fetched, and as a default value on the "create" page. In the video above I show embedding the VB app in SaaS, but in some cases you might actually open the VB app in a separate tab/window. To do that you use the page composer to add a hyperlink to your Cloud Apps page. Then you use the URL of the live VB app in the same way as the destination of this link. In the Target Frame attribute of the link you'll probably want to use _blank. One part that is not covered in this blog, and that you'll likely want to configure when embedding VB apps in Oracle Fusion Apps, is setup of single-sign-on between VB and SaaS. There is a solution doc that explains how to setup federated identity between Oracle SaaS and PaaS here. Another good resource is the blog entry from Aparna that cover setup of identity propagation between Visual Builder and Oracle Cloud Applications.   

In some cases you will want to access Oracle Visual Builder application through an interface built with another product/service. For example, embed the VB app in a portal or another app. Embedding...

Visual Builder Studio

Analyzing Your Code Dependencies for Vulnerabilities with Visual Builder Studio

Most of the projects developed today rely on open source libraries - it is likely that your project does too. While using these libraries accelerates development by relying on proven solution for common needs, it also introduces a potential risk factor. Over time people discover vulnerabilities in many of these libraries. While most of the issues will get fixed in newer versions of the libraries, it is up to the consumer of the library to make sure they are up-to-date on the latest version. It is a hard task to constantly track the libraries you are using and to keep them up to date. For projects that are already in production, and have not kept their libraries updated, this is an even bigger risk opening organization to potential malicious attacks leveraging these known vulnerabilities. Automating a review process of the libraries used in your code against databases of known vulnerability can help you stay one-step ahead of attackers. This is exactly what the Dependency Vulnerability Analyzer in Visual Builder Studio helps you achieve. In the demo below you can see how simple it is to automate the process of reviewing the libraries your code uses, get a report about any known vulnerability in those libraries, and even how fixing your code can be streamlined. The demo specifically uses a project that is managing the libraries used through NPM - and scans those dependencies from the package.json file against several repositories of known vulnerabilities. You can also conduct similar checks for Java projects that leverage Maven and pom files to manage dependencies. Check out the demo, and start implementing these security check for your project today!    

Most of the projects developed today rely on open source libraries - it is likely that your project does too. While using these libraries accelerates development by relying on proven solution for...

Oracle Visual Builder Cloud Service

Leverage ORDS with Visual Builder to Access Oracle DB - an OpenAPI Update

A while back I posted a blog/video showing how to access Oracle ATP DB through ORDS from Visual Builder. One update that happened since then on both the ORDS side and the Visual Builder part is support of OpenAPI/Swagger standard. This accelerates and simplifies adding ORDS based REST services to a VB app and creating apps leveraging them.  ORDS is a simple solution for anyone looking to build Visual Builder based apps on top of existing tables in an Oracle DB. ORDS provides a very simple way to expose a set of REST services on top of tables (and other DB objects). Once the services are created you can add them to Visual Builder and consume the data they expose. While in the previous blog I showed how to add specific endpoints, with the support for OpenAPI on both sides, you can use the "Define by Specification" approach to create many endpoints in one simple action in VB (and have the correct mappings to the specific actions and data types).  To get to the ORDS OpenAPI meta-data, add open-api-catalog to the URL for your object so the URL will be something like: https://servername/ords/schema/open-api-catalog/tablename/ Check out the demo below to see the end to end flow: One more thing to remember, ORDS uses a specific format of REST requests to provides capabilities such as filtering, sorting, and paginating through data. If you want Visual Builder to leverage these features, you'll need to add a transform option that specify how to do this. You can find an example of such code for ORDS in the previous blog.

A while back I posted a blog/video showing how to access Oracle ATP DB through ORDS from Visual Builder. One update that happened since then on both the ORDS side and the Visual Builder part is...

REST Backends

Visual Builder Service Connections - Connection types

Starting from 19.4.3, Visual Builder gives you more control on how to connect to REST APIs using Service Connections, specifically in the area of CORS (Cross Origin Request Sharing).   As pointed out in an older blog post, VB can connect to external REST APIs in two ways Using the browser/client JavaScript to connect to the API, commonly referred as Direct Using the VB server side proxy to act as an intermediary between VB and the external API, referred to as via Proxy These are represented in the below figure: Previously, this option was controlled through what was set as an authentication method, plus a checkbox known as the "Token Relay" at the service connection.  These have now been standardized and made available as an attribute called the "Connection Type" next to the authentication in the Server settings of the Service Connection (or Backend) These values that the Connection type attribute can take are : Dynamic - Service supports CORS Dynamic - Service does not support CORS Always use the Proxy Inherit from Catalog - this option only appears if you have a Service Connection created from a catalog based backend, and want to inherit the same connection type of the backend. The Dynamic options are the recommended options, where Visual Builder best decides the route to chart from the app to the external service (i.e. whether to go directly or via Proxy), based on whether the service supports CORS or not.  However, you can always choose the third option (Always use the Proxy) and make sure that all requests are routed via the Proxy.   The advantage of using a Dynamic connection type To decide the best route from VB app (which is a JavaScript SPA running on a browser or a device), a number of conditions need to be inspected. The optimal way for VB to communicate with the external REST service is always going directly.  Proxy based connections add latency because each request and response has to pass through the proxy Direct is the thus method of choice, except in case of those REST services that don't support CORS.  This means that the REST resource is not amenable to being connected from a browser based environment.  In these cases the only way is to connect via a Proxy. Direct is also not suitable in case of authentications that are in clear text i.e. Basic Auth ( even though it is base64 encoded, the same can be decoded ) Direct is also not suitable for authentications that always need to be computed on server side (e.g. OCI Signature Authentication) Another complexity is that CORS only comes into play when it is a web app or a progressive web app (PWA) that is making the REST call.  Native mobile apps are agnostic to this.  So even if you had a REST resource that didnt support CORS, you could still connect to it directly if you are running a native mobile app on device.  But you cant do it when you connect to the same REST resource via a web app, a PWA or even when you preview the app in VB's design time environment If you use HTTP (hopefully only for development purposes), then you cannot use Direct, as VB pages are served via HTTPS Phew, those are a lot of things to check!  Fortunately, you don't have to check any of these yourself when you opt for "Dynamic" with the relevant CORS option and VB automatically figures out whether to use "Direct" or "Proxy" If you are unsure about the CORS status of the API you want to connect to, you can try testing it in the Test tab which will report if you are unable to use the "Dynamic - supports CORS" option.  In this case, the next best choice is using the "Dynamic - doesnt support CORS" option. And if for some reason, you always want to route your request through the VB proxy, that is available too with the choice of "Always Use Proxy" How do the Dynamic options work VB will decide the route of communication with the REST API with Dynamic connection types based on the following parameters Choice of Authentication method - Specifically Basic Auth and OCI Authentication will always go via the Proxy The environment (browser/device) which is being used to make the call to the REST API Whether the external REST API supports CORS or not Here is a diagram showing how VB decides which option is the most optimal during runtime:   The advantage of the new Connection Type attribute is that the developer doesn't have to decide the choice upfront - VB does it for you. The developer simply has to indicate whether or not the REST resource being connected to supports CORS for this particular VB domain.  Ofcourse, the developer also has the flexibility of completely ignoring the optimality algorithm and always route requests through the proxy by using the "Always use Proxy" option  

Starting from 19.4.3, Visual Builder gives you more control on how to connect to REST APIs using Service Connections, specifically in the area of CORS (Cross Origin Request Sharing).   As pointed out in...

REST Backends

Leveraging Application Profiles to Switch Backend Servers with Visual Builder Studio

Last year I wrote a blog post showing how to switch REST backend as part of the CI/CD of your Visual Builder application. Since then we released both an update to Visual Builder - which included the new servers, backends, and profiles features - as well as the new Visual Builder Studio - which provides a declarative way to define CI/CD automation for VB apps. So, I thought it would be a good idea to show how you combine the two to automate deployment that uses the specific backend you need. The key to the simplification of the process is the use of Application Profiles - a feature that we introduced in our March 2020 release. App profiles work together with the concepts of services and backends to define a "pluggable" set of servers your app connects to. You can define multiple profiles for an app, and in each one contains a different set of servers that will be used by the application. The server definition can dynamically control not just the server end point, but also aspects like the authentication the services need, the headers, and even the way you reach them (direct or through our proxy). More about these features in these two blogs by Aparna part1, part2.  In the video below I start by creating a new server connection that has the same REST endpoint but on a different server with a different authentication schema. Then I define a new application profile, that will be using the new server definition to access data. Next we are switching to Visual Builder Studio - where we leverage the new Oracle Deployment build step to define a CI/CD pipeline that deploys our app. I have one deploy job that uses one profile (dev), and then I run another deploy job that deploy using the alternative app profile (qa). As you'll see while the application behaves the same in both cases the data is different in each deployment since they are coming from different sources. It's important to mention that VBS is just providing your with an easy to use declarative interface to define deployment (and packaging) for VB apps. If you need to do the work from outside VBS, you can use the VB grunt commands that do app packaging and deployment. These grunt commands now have a new "profile" parameter used to indicate which profile to use. With this approach you can have the same code base (which is stored in your Git repo) deploy to different location with different backends. All in an automated way.  

Last year I wrote a blog post showing how to switch REST backend as part of the CI/CD of your Visual Builder application. Since then we released both an update to Visual Builder - which included the...

Oracle Visual Builder Cloud Service

Working with Asynchronous Event and Websocket in Visual Builder

Written and Developed by Carlos Casares Oracle Spain Creating applications that interact with data in a synchronous way in Visual Builder is quite easy. But sometimes your application needs to be notified asynchronously or needs to receive so-called unsolicited message. These are messages that are not part of a response of a previous request, might be received at anytime, and need to be handled accordingly. How would you handle these asynchronous events? You have several approaches to get notified from an external event: Using a polling mechanism by means of regular calls initiated from the app/browser every X seconds (or milliseconds or minutes…). This approach is heavy for both the client (app running in your browser) and the server. Another (a bit unknown) approach is Server-Sent Events or subscribing to MQTT topics through the Paho Javascipt library. The one we’re going to focus on is Websockets. (For more information about polling vs. websockets vs. sse, see here). Websockets As per Wikipedia: The WebSocket protocol enables interaction between a web browser (or other client application) and a web server with lower overhead than half-duplex alternatives such as HTTP polling, facilitating real-time data transfer from and to the server. In brief, you can establish a bi-directional communication channel between your application and a websocket server (which most likely will be different than the web server itself). Such communication is initiated by the web application (and thus, from the browser) and once established, you will have a channel to send (browser-to-server) and receive (server-to-browser) messages. Websockets runs on top of the HTTP protocol and supports plain and SSL/TLS communication. When used with VB, you’ll need to connect to the server using Websockets Secure (or WSS) as your browser will not allow to use plain HTTP/WS in a HTTPS served application. Websocket is available as default object in HTML that can be easily used in your Javascript code such as:   var aWebSocket = new WebSocket(url [, protocols]); Once created, you just need to set a number of callbacks to attend the unsolicited events you’re going to receive. And the object provides a send() method to send messages from the app/browser to the server. You don’t need to link or include any external library to be able to use Websockets in your application. It is that easy! Maybe the most challenging part of Websocket programming is the communications error handling. Take into account that once you open a websocket channel, it will remain opened as long as your internet connection is stable. A network glitch or outage, will simply close the connection and your code is responsible to re-establish it again. From a Server point of view, you can’t do anything when the client lost its connection. Remember, the client (app) is the one who initiates it, not the server.      There are many ways to implement a Websocket server, in many different languages (Java, Javascript/nodejs, C#, Python, etc). But, apart from the Websocket object available by default, there are also different client libraries that provide extra features and ease the tasks involved in Websocket programming. One of the most famous and my personal favorite is socket.io, that can be used for both client and websocket server implementation. Actually, if you plan to use socket.io as your client library, you must connect to a socket.io-based server (socket.io library also supports other transports whenever Websocket is not supported by your browser). Socket.io handles communication outages very well. You, as the app programmer, won’t really need to worry about them (apart from handling an offline situation, of course). Using Socket.io in Visual Builder While Oracle Visual Builder does not support a declarative “Websocket object” that can be easily dragged and dropped into your apps, it is very easy to extend your applications writing your JS code or importing third party libraries and extend Visual Builder application with a Websocket channel (using, in my example, the socket.io library). You just need to follow these simple steps: 1)    Import/link the socket.io client library in your app 2)    Create the socket.io object and establish the connection with your server 3)    Send messages whenever you want or 4)    Receive (unsolicited) messages and trigger a VB Custom Event (which will actually handle the message, and interact with VB objects) You can add socket.io to your VB app by downloading the socket.io client library and import it in your VB app or by loading it at runtime from a CDN using require.js. You can do so in the JS section of your appplication, flow or page, depending if you want the websocket to be available at app, flow or page level respectively:   define(['https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js'], function(io) { (the CDN link used may vary; just do a Google search for socket.io client library cdn and get the latest version) Declare the socket variable outside of your prototype functions so that it doesn’t get initialized every time and also you can have multiple JS functions for different purposes that will make use of the Websocket communication: var socket; You can handle the incoming messages within your JS code, as part of the callback function. However, you will most likely want to run Action Chains as part of such handling. If so, you will need to get your app EventHelper object that will allow you to fire custom events. Declare it along with the socket variable: var socket, eventHelper; and get it in your PageModule (or FlowModule or AppModule) constructor. Such constructor is always part of your default JS code: var PageModule = function PageModule () {}; enhance it as follows: var PageModule = function PageModule(context) {   if (context) {     eventHelper = context.getEventHelper();   } }; Note: PageModule() (or FlowModule() or AppModule()) seems to be invoked several times during initialization, and the context object is not always valid. Thus, check if it really comes in before getting an error when trying to get the EventHelper from an undefined variable. Then, you need to write a prototype function that will handle all the Websockets communication (connection, disconnection and message reception). If you want to also send messages from your VB app (not part of this example), you can write a separate prototype function that will invoke the send()or emit() methods as follows: socket.send() socket.emit() You can use namespaces when sending (and receiving) messages with the socket.io library. Check the official documentation on that. This is the complete code for the prototype function in my example:   PageModule.prototype.startWebsocket = function(start, hostname, port) {   if (start == true) { /** Websocket/socket.io stuff **/     console.log("***********: " + hostname + ":" + port);     socket = io("wss://" + hostname + ":" + port, { autoConnect: false, transports: ['websocket'] });     var messageHandler = function(message) {       console.log("******* [WEBSOCKET]: " + "Message received: " + JSON.stringify(message));       if (eventHelper) {         eventHelper.fireCustomEvent("newMessage", { message: { timestamp: Date().toString(), data: message.data } } );       }     };     socket.on('connect', function() {       console.log("******* [WEBSOCKET]: " + "CONNECT");       if (eventHelper) {         eventHelper.fireCustomEvent("changeWebsocketStatus", { connected: true });       }     });     socket.on('disconnect', function() {       console.log("******* [WEBSOCKET]: " + "DISCONNECT");       if (eventHelper) {         eventHelper.fireCustomEvent("changeWebsocketStatus", { connected: false });       }     });     socket.on('message', messageHandler);         socket.connect(); /** Websocket/socket.io stuff **/   } else {     if (socket) {       socket.disconnect();     }   } } It receives three input parameters: start: a boolean variable that indicates whether I must connect or disconnect the websocket communication hostname: hostname (or IP address) where the socket.io server is located port: port used by the socket.io server If (start == true) the code tries to establish the connection and define some callbacks that will be invoked under certain events (connect, disconnect, and message in the example): socket = io("wss://" + hostname + ":" + port, { autoConnect: false, transports: ['websocket'] }); Note how we’re using “wss” as the protocol (equivalent to HTTPS for websockets) as your browser will not allow you to establish a plain connection in an SSL served application. Also, we’re forcing socket.io to use websocket protocol and not to auto connect.  Remember the io object is defined during the requirejs declaration: define(['https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js'], function(io) { We define the messageHandler function that will be later linked to the message callback definition. In this function we simply fire a VB custom event named newMessage:   var messageHandler = function(message) {   console.log("******* [WEBSOCKET]: " + "Message received: " + JSON.stringify(message));   if (eventHelper) {     eventHelper.fireCustomEvent("newMessage", { message: { timestamp: Date().toString(), data: message.data } } );   } };   As part of the socket.io sample server implementation, we’re sending the following message structure: { data: "any text string" } And thus, we’re accessing its content through message.data in the above code. Of course, you can send literally whatever you want (binary, plain text, JSON, etc). Remember you can set your own payload to your custom events, but remember its definition when processing it in the ActionChain. In the example, we’re sending the following JSON object: {    message: {       timestamp: Date().toString(),       data: message.data    } } We now set the callbacks for the connect and disconnect events, where we will fire two different custom events to update the status in the application: socket.on('connect', function() {   console.log("******* [WEBSOCKET]: " + "CONNECT");   if (eventHelper) {     eventHelper.fireCustomEvent("changeWebsocketStatus", { connected: true });   } }); socket.on('disconnect', function() {   console.log("******* [WEBSOCKET]: " + "DISCONNECT");   if (eventHelper) {     eventHelper.fireCustomEvent("changeWebsocketStatus", { connected: false });   } }); Finally, we set the message callback handler and (try to) establish the connection: socket.on('message', messageHandler);     socket.connect(); Note we’re not defining any method or handler for reconnections. The magic of socket.io will handle all that for us! The last piece of code is to disconnect the existing connection (if any) should the start input variable is false: if (socket) {   socket.disconnect(); } And that’s all for the JS part! The Visual Builder App Now it’s time to configure the VB application: 1)    Create the variables and UI  2)    Define custom events 3)    Create the Action Chains that will be triggered by my custom events 1)    Create Variables and UI We start from an empty VB project where we create a new Web App named wssclientsample, and will use the default template (“None”) and do everything in the pre-created main flow and main-start page. Also, all variables, code, etc, will be at main-start page level. First, we’re going to create the following variables:   Var Name Type Purpose hostname Strint Binding var for WSS hostname port Number Binding var for WSS port status String Binding var for to dispaly cnx status on page start Boolean Binding var for Switch component to start/stop the connection message Array of Object { timestamp: "string",   data: "string" }   Object that will contain all received messages adp Array Data Provider Bind Data to message variable Binding var for the Table component The page UI is: ​​​​​​ Components data binding (in order): Component Data Binding Input Text $page.variables.hostname Input Number $page.variables.port Switch $page.variables.start Input Text $page.variables.status Table $page.variables.adp The Switch component triggers the following Action Chain through the value event, to connect or disconnect the websocket channel: The Call Module Function invokes the JS startWebsocket() method with the following mappings: 2)    Define Custom Events Within the startWebsocket() JS method, you are triggering some custom events based on some events that happen as part of the websocket implementation: Custom Event Name Payload Variable Payload Type Pupose changeWebsocketStatus connected Boolean Fired when connection status changes newMessage message Object {"timestamp":"string", "data":"string"} Fired when a new message has been received Note how the fireCustomEvent() method sends the same payload type as defined in the Custom Event: eventHelper.fireCustomEvent("changeWebsocketStatus", { connected: true }); eventHelper.fireCustomEvent("newMessage", { message: { timestamp: Date().toString(), data: message.data } } );   3)    Create Action Chains that are Triggered by Custom Events The Custom Events are triggered from the JS code that controls the websocket connection and message reception. We need to implement the Action Chains that will be triggered by those Custom Events: Custom Ebent Action Chain Input Type changeWebsocketStatus setStatus status Boolean newMessage data message Object: {"timestamp": "string"   "data": "string"} The Action Chain code is very simple, we just assign a variable on each: setStatus: data: …and with this, we’re done with all VB stuff! The Server Now, you will be wondering which Websocket server your VB app is going to connect to. As part of this sample, I have written a very simple socket.io-based Websocket server that can be found here: https://github.com/oraclespainpresales/vbcsWebsocketsServerDemo If you plan to run it locally, you’ll have to deal with the SSL certificates. Remember that you need to host your websocket with SSL or the browser will reject the connection. I use a valid certificate and load it here in the server code: const optionsSSL = {   cert: fs.readFileSync(SSLPATH + "/certificate.fullchain.crt").toString(),   key: fs.readFileSync(SSLPATH + "/certificate.key").toString() }; However, you will need to have your own, either a valid one or a self-signed. If the second, you will need to upload it to your VB instance. See here for more info. Remember to run a npm install to download and install all the npm packages needed. Once you run your server, remember your IP address/hostname and the port used and type them in accordingly in your VB app: When ready, you just need POSTMAN, cURL or any other REST client to send the POST request to the server which will forward it as a websocket message to your VB app:

Written and Developed by Carlos Casares Oracle Spain Creating applications that interact with data in a synchronous way in Visual Builder is quite easy. But sometimes your application needs to be...

Oracle Visual Builder Cloud Service

The New Visual Builder Studio - Introduction for Visual Builder Developers

Oracle announced the availability of Oracle Visual Builder Studio this weekend, and if you are a current developer working with Visual Builder - you should learn more about how this service can help your development team deliver better Visual Builder applications faster. Visual Builder Studio builds on the functionality previously available in Oracle Developer Cloud Service (such as Git repositories, CI/CD automation, issue tracking and agile planning) and adds to it a set of features specifically aimed for developing Visual Builder Applications (or Visual Applications for short). The result is an ideal platform for teams that want to improve their development flow, and automate the delivery of their apps. Here are some of the key new features that will be of interest to you as a Visual Builder developer. Visual Application Project Template This new Project Templates makes it very easy to setup a project for your team with the base artifacts you need to manage and deliver code. Including a template app in a git repo, build jobs to package and deploy the app, and an environment set to point to your Visual Builder instance. Environments Visual Builder (and Oracle Integration Cloud) instances can be mapped to your project environments, so you can see the status of your server, and drill down to see the apps deployed on them. You can manage those apps from this interface allowing you to lock, export/import data, and even undeploy apps. Designer tab with Workspaces A new top menu option in VB Studio is the Designer tab, in which you can create worksapces - the equivalents of your own local git clones of the application - in which you develop and add your code changes. From that tab you can directly invoke the visual designer interface for working on your app. This visual designer will initally look very similar to the one you are currently working on, but on further inspection you'll notice some new additions including... Deep Git Integration Visual Builder Studio places Git at the heart of your development cycle. Your application code is stored in a git repository and all your changes are managed through branches. The git menu now includes additional git commands (such as switch branch) and removes the need to setup connection to the git repo as this is now built-in. In addition, a new git panel section in the IDE shows you the git status of your application files, and will help you visually merge code conflicts between branches. A new Publish button enables you to merge code changes from your branch into the master branch, including the ability to start a code review process for your changes, so other can review, comment and approve or reject changes. Visual Builder CI/CD Automation Visual Builder Studio includes a set of build steps that will allow you to declaratively define a build/deploy/manage cycle for your apps across servers (instead of manually writing grunt tasks). Build steps include pacakge and optimize your source, export/import data, and lock/unlock/undeploy for an app. In addition you can now deploy your app to VB instances using the "Oracle Deployment" option. There is More All of these capabilities integrate with the other features of Visual Builder Studio that include: Manage team members and their roles Issue tracking system Agile dashboards and development sprint tracking Wikis for sharing info CI/CD for other project artifacts If you are currently using Visual Builder and are interested to try out Visual Builder Studio, have a look at our documentation for the setup steps and tutorials.    

Oracle announced the availability of Oracle Visual Builder Studio this weekend, and if you are a current developer working with Visual Builder - you should learn more about how this service can help...

User Interface

Upgrading the Sample R13 SaaS LightBlue Theme for Visual Builder 19.4.n

If you have Visual Builder applications that used the sample R13 SaaS LightBlue theme from an earlier version, then you will need to go through a simple upgrade process before trying to run the application under Visual Builder 19.4.  Just to explain, there is a jump in the major version of the Oracle JET UI toolkit between these two versions (version 7 of JET to version 8 in this case) and the fallout from that upgrade is that any themes developed against the old version of JET need to be re-generated. The good news is that we've done the hard work for you and you'll just need to go thought the following simple steps to consume this new version of the theme. Note that you can carry out these steps, even before your Visual Builder instance is migrated to 19.4, all you need to do in that case is to skip the final step until after the upgrade has taken place. Also note that if you create a new application in 19.4. with this SaaS LightBlue theme it will automatically have the correct theme files and you will not have to carry out these steps. Step 1: Download the updated version of the theme files from GITHub  Step 2: Open your Application, expand the WebApp in question and right mouse click on the resources node.  Choose the Import option and select the ApplicationsCloudUI-3.0.0.zip file you have downloaded, then press the Import button. Make sure you are importing into the /resources top level folder as shown here. Step 3:  Select the application in the navigator and open its Application Settings panel. In the Theme select list, select the new 3.n.n theme as shown here (version number may update over time): For reference Visual Builder 19.1 (JET 6 runtime): use 1.1.0 of the theme Visual Builder 19.3 (JET 7 runtime): use 2.0.0 of the theme Visual Builder 19.4 (JET 8 runtime): use 3.0.1 of the theme

If you have Visual Builder applications that used the sample R13 SaaS LightBlue theme from an earlier version, then you will need to go through a simple upgrade process before trying to run the...

Visual Builder Identity Propagation Setup with SaaS

Visual Builder is commonly used to build applications leveraging REST APIs from Oracle (Fusion Application) SaaS like HCM, CRM and ERP.  A frequent scenario we come across in this space is the Identity Propagation from Visual Builder to SaaS via REST APIs.  In this blog we discuss on a high level the setup that goes into configuring this, which is mostly done in IDCS and SaaS.  EDIT - Note that if your SaaS instance has been pre-provided with an Identity Cloud Service, and your VB instance is also using the same Identity Cloud service, all the configuration needed for identity propagation between SaaS and VB will be automatically configured.  You would only need to add any synchronization (see Synchronization between IDCS and SaaS section in the blog) and configure the SaaS instance as a backend in the VB Tenant Catalog  The remainder of the blog assumes that you dont have a pre-configured IDCS instance. This is not meant to be a detailed step-by-step documentation (which is already published here ), but is meant to demystify certain parts of the setup and serve as a checklist, so that the developer knows the different purposes of the configuration. First, a few concepts: Identity Propagation - refers to the ability of the application (mobile or web) to pass on the identity of the user who has logged in to the application to a service being called.  At a very high level this is made possible by the two applications (client and the resource) trusting each other and 'asserting' the user's identity whenever required.  Identity Propagation is different to Fixed Credentials in which the service being called sees the same credentials no matter who has logged in, which is illustrated in the below figure OAuth 2.0 - is an authorization protocol that allows a client application to get access to resource applications services either on behalf of the client application or on behalf of a particular user by orchestrating a flow of interactions between the client application/user and the resource application.  The access is typically encoded in a JWT token format.  OAuth 2.0 consists of a number of grants which allow a variety of use cases.  A client application in OAuth 2.0 is typically recognized by its client id and optionally has a client secret.  Another important construct in OAuth is the scope, which limits the access that the client application is allowed - i.e. "profile/me" allows access to the me endpoint only, "/sales" allows access to the entire sales resource. Visual Builder relies on Identity Cloud Service (IDCS) for all its identity propagation use cases and these are carried out by various OAuth flows - especially one known as "JWT Assertion/User Assertion" flow.  Now we start our setup to achieve Identity Propagation between VB and SaaS.  Note we refer to SaaS and FA  (Fusion Apps) interchangeably in this blog. Broadly the setup is divided into four areas : SSO setup (using SAML) OAuth federation setup Extra OAuth federation step for VB Synchronization of users and optionally roles between IDCS and SaaS It is recommended to read this entire blog to have a high level picture first and then implement the detailed steps given in the official documentation Before we begin, we are considering the following fictitious example: SaaS instance  - https://abc.fa.oraclecloud.com SaaS REST API which we want to connect from VB  - https://abc.fa.oraclecloud.com/crmRestApi/resources/latest/accounts IDCS instance which we want to federate with SaaS - https://idcs-def.identity.oraclecloud.com VB instance we want to achieve the federation in - https://vb1-tenant1.builder.ocp.oraclecloud.com (in case of VB available through Oracle Integration Cloud / OIC, this would be the same as the OIC instance - e.g. https://ic1-tenant1.builder.ocp.oraclecloud.com )   SSO setup Single Sign-on (also called Web based SSO) allows us to use a single login and authentication provider for multiple sites and systems.  The most popular way to do this is by using SAML (Security Assertion Markup Language) in which one system is designated as an Identity Provider (IDP) and the other system is known as the Service Provider (SP, also called Relying Party in some literature).  Put simply, the SP will allow a user to access its resources like web pages, if the user is deemed to have been authenticated by the IDP.  This mechanism relies on cookies and browser redirects to move information from SP to IDP and back to the SP once authentication is done.  The SAML based setup requires some metadata and certificates to be exchanged between the SP and IDP - i.e. the SP metadata needs to be uploaded in the IDP and the IDP's metadata needs to be uploaded in the SP In our case, we have two distinct systems, IDCS (and thereby VB) and SaaS, which has its own Identity Provider.  Most of the customers opt for a setup with SaaS as the IDP and IDCS as the SP for SAML setup (although the reverse is also possible) The high level flow for this setup is as shown below. Each step is carried out in either IDCS, SaaS, VB which is also shown in the diagram     Note the final step requires that you create an SR to hand the further steps to Oracle Support.  The OAuth Federation setup also requires a similar SR, so it is recommended you log a single SR for both (as given in the official documentation)   After the SR is completed, you can Activate the federation and also setup synchronization between SaaS and IDCS.  Note that you would need to setup the synchronization to at least have some users to test the same. OAuth based federation setup SAML based SSO is good, but it requires cookies and redirects -  that is, it always needs to be carried out in a browser based environment.  What if you need to call a REST API from one app to another without relying on a browser redirect?  Here is where OAuth based federation comes to our rescue.  This is different that SAML based SSO in that it doesnt require the flow to execute on a browser.  This is achieved by an "access token" (typically an JWT token) which is added to the Authorization HTTP header while calling the REST API.  The access token is special it that it encodes the information about the user as well as a signature that ensures that a given Identity Provider has authenticated this user. VB requires that you configure OAuth setup with SaaS as well.  Below is the diagram that shows high level steps to do so   At this point (step 5b) you need to log an SR (it can be the same SR logged earlier) to add the IDCS signing certificate in SaaS to establish trust between SaaS and IDCS.  Once the SR is complete, you will receive an OWSM certificate which you need to upload to the FA1 IDCS application Extra OAuth step for VB There is an extra step needed specifically for VB and SaaS integration.  You need to create an IDCS OAuth Resource + Client application similar to FA1 with a small change in the Primary audience - instead of https://abc.fa.oraclecloud.com, you should have https://abc.fa.oraclecloud.com:443 (i.e. :443 appended at the end of the SaaS base URL).   Make this a trusted application too, uploading the same OWSM certifcate Almost done! After both FA1 and FA1:443 are made trusted applications and activated, configure the Tenant catalog in VB by logging as an administrator and going to (tenant) Settings -> Services and adding an "Oracle Cloud Applications" backend (see Case 3 in this blog) with authentication "Oracle Cloud Account".  If you do the optional settings of adding the VB origin (https://vb1-tenant1.builder.ocp.oraclecloud.com in our example) to the CORS allowed-origins in SaaS. you can use the connection type - "Dynamic supports CORS", else you would need to use the other two connection types. (To know more about CORS, 'Direct' and 'Proxy' based flows in VB, refer to this documentation)   With this setup complete, you can start creating Visual Applications with Service Connections to SaaS configured with "Oracle Cloud Account" provided you have some federated users in IDCS to login and test.  If you dont have federated users, go to the synchronization task.     Synchronization between IDCS and SaaS The last step that we need to do is to create a bridge between SaaS and IDCS which will synchronize all relevant users and roles to IDCS.  For this we need to create a new IDCS OAuth client application which has admin privileges i.e. can create users and roles within IDCS.  Then we configure SaaS with the ability to use this client application (by providing its client id and credentials) in a Task that is scheduled to run immediately or repeatedly based on your use case Once this is done, all relevant users in SaaS will start appearing in IDCS as federated identities.  Roles in SaaS will be migrated to IDCS as groups. Note that synchronization can be also configured from IDCS to SaaS, which we are not depicting here.  You can refer to the official documentation for more details. Now that you have a high level idea, you can follow the detailed step-by-step guide for establishing SSO and federation between IDCS and SaaS.  Note that the documentation doesn't have the extra step for VB mentioned here, which you would need to do as well. To test the setup, you would need to create a Service Connection to a SaaS REST API either from a Catalog, or an endpoint or using the specification, and set its authentication as "Oracle Cloud Account".  We recommend a Connection Type of "Dynamic - supports CORS" - which will work if you had followed the best practice of adding the VB origin to the CORS allowed-origins in SaaS, else you can set it up to "Dynamic - does not support CORS".   Reminder, creating the Service Connection from Catalog requires you to setup backends first. Here are some of the issues commonly encountered during this setup Not able to download the IDCS signing certificate - By default, you will not be allowed to download the IDCS signing certificate.  In order to allow this, go to IDCS -> Settings -> Default settings -> Enable Access Signing Certificate Not able to see option to add the scope to the VB instance - this is basically your user lacking Application Administrator privileges in IDCS.  Once you get these, you should be able to see the relevant button Getting a scope related error while testing Service Connection  - This indicates that the Visual Builder instance either doesnt have the correct scope OR the resource applications that represent the scope are not correctly configured.  Things to check are as below: Make sure that the resource applications (FA1 and FA1:443 in our examples) do not have the forward slash '/' in their primary audience, and have the '/' in the scope Both resource applications should have been made "Trusted" and the OWSM certificate given by Oracle support should be added to both Make sure that the Visual App in which you are testing the Service Connection is created after the whole setup was done            

Visual Builder is commonly used to build applications leveraging REST APIs from Oracle (Fusion Application) SaaS like HCM, CRM and ERP.  A frequent scenario we come across in this space is...

User Interface

Editable Tables in Visual Builder - The Oracle JET 8.1 Approach

Last year I wrote a blog about how to create editable tables based on version 6 of JET. That entry has been quite popular, but since the publishing of that blog things have changed in both Oracle JET and Oracle Visual Builder, and there is a new pattern we are now recommending for handling editable tables. The new pattern is offering better performance and eliminates some refresh issues that users encountered with the old approach. Below you can see a demo showing how to build an editable table in VB from scratch following the approach shown in the JET 8.1 cookbook sample. Note - In general our UI expert are not in favor of editable tables, especially if your users would end up using their application on a mobile device with touch gesture. A better UI pattern they would recommend is editing in a pop-up or in a form next to the table. Here is a blog about editing from a pop-up - which is also simpler to implement :-) . A few points about the solution: The table should only show input component for the row you are currently editing. This is mainly for performance reasons. Rendering multiple lines with input components in them is a heavy task for the browser, and using just one line for editing reduces the time and memory needed to accomplish page rendering. The table is based on an ArrayDataProvider - a variable that keeps an array of the records being edited on the client - allowing you to modify them over time (unlike ServiceDataProvider). Note that in the new March version of Visual Builder (19.4.3) we updated the ADP implementation so in the source you'll see this as "type": "vb/ArrayDataProvider2". The actual editing is done on an object that replicates the current row being edited - this way when you change values we don't need to refresh the full array on each field change. Once you are done with the editing of the row, we update the array of records modifying just the row that you changed. We leverage two events on the table to catch the beginning and end of the row editing process. The demo shows one approach to saving the data to the backend - sending a REST call to the backend to update each of the rows from the array. This of course is not the recommended approach - since you can be much more efficient sending just the rows that changes, and batching those transactions into a single REST request. I'm planning to have another blog entry showing this approach in the future [Update - the blog about this is here]. Another approach you could take is to send an updated row to the backend immediately as you leave the editing mode. This is assuming your use case is ok with this immediate commit without an additional operation by the user (such as clicking a save button). Here is the full process end to end: If you are looking to skip some parts then the flow is with time stamps so you can fast forward to the parts you need: Define an ADP and populate it with data (0:50-3:30) Define a table component and hook it up to the ADP (3:30-4:15) Switch the table to use column templates for read/write status (4:15-9:05) Create a row object and hook it up to the input components (9:05-10:00) Add methods for populating and reading from the row object (10:00-13:30) Add an event to loop over rows and save to the database (13:50-16:10) Set columns width to eliminate column flashing (16:10-end) Wait There is More... If you found this video useful, you should also look at these two follow ups that cover additional tips: Click to Edit, and Submit Only Changed Rows Dependent Lists in an Editable Table  

Last year I wrote a blog about how to create editable tables based on version 6 of JET. That entry has been quite popular, but since the publishing of that blog things have changed in both Oracle JET...

User Interface

Implementing Search-As-You-Type in Oracle Visual Builder

Introduction  When presenting a collection based interface to end users you'll often want to provide a search field that can be used to filter that data.  Conventionally you might accomplish this using the basic pattern of creating an input field above the table or list-view which is bound via it's value to a page variable that is in turn bound to a filter criteria on the Service Data Provider that is driving the collection dataset.   With this pattern, no additional wiring is required for the page developer, however, the end user does need to type a value into the search field and then press tab to update the search variable (this happens as the user leaves the field). As soon as the search variable is changed this then has the side effect of notifying the SDP of the criteria change which in turn automatically triggers the refresh process and fresh query from the Business Object (or other service)  So, what if you want to refine this so that the user does not have to leave the search field i.e. as the user types the table or list-view is continually re-queried? Raw-Value to the Rescue It turns out that this is pretty simple to do.  Rather than binding the search variable to the value property of the <oj-input-text> instead you can bind the same variable to the rawValue property.  Using the following syntax: <oj-input-text raw-value="{{$page.variables.searchTerm}}"></oj-input-text> Unlike the conventional value property, rawValue updates before the user navigates out of the field. So every keypress will cause an update to the search term and likewise cause the SDP to refresh.  Hold-on That's too Often! One problem with the use of rawValue is that it does change with every character that the user types.  Now that may be OK on mobile because of the slowness of using a virtual keyboard, of the service call is quick to execute, however, in cases of expensive REST calls of fast typing it may be too much!  For example, if the user types "Visual" into the search field then this would end up submitting 6 REST calls with the search criteria as follows:  "V" "Vi" "Vis" "Visu" "Visua" "Visual" That seems a little wasteful, particularly is the user types quickly and knows the full term they want to search on. So how to alleviate this? Well there are couple of approaches.  First of all you can change the definition of the searchTerm variable to set a Rate Limit as shown here: The Rate Limit throttles the number of updates that can happen to the variable with the number used representing the number of milliseconds between updates. In many cases, just playing with the rate limit can tune the number of SDP changes that are triggered and provides just what you need.  More Advanced Control with <oj-sample-input-typeahead>  If setting rate limit does not quite provide the performance that you need you can add the sample component oj-sample-input-typeahead into your Visual Builder Project. You can find this in the component browser This component is a drop in replacement for a standard <oj-input-text> except that it internally controls the update of rawValue so that updates only happen when user typing pauses or stops. with this in place, our search for "Visual" would only trigger one SDP update / REST call which is much better.  The <oj-sample-input-typeahead> can be tuned using it's typeaheadWait property (Labeled as Wait Time in the property inspector) which defines how long a pause (in milliseconds) is needed before the change to rawValue is propagated.  Note that components with the oj-sample prefix are indeed samples and are unsupported - so use at your own risk.  In a future article I'll show you how you can copy and adapt these example components for yourselves.

Introduction  When presenting a collection based interface to end users you'll often want to provide a search field that can be used to filter that data.  Conventionally you might accomplish this using...

Visual Builder - Migrating Sample Components to the Latest Versions

Introduction In Oracle Visual Builder we provide a capability to add additional custom components into the page designer component palette from a shared catalog. As part of this offering we have pre-seeded the catalog with a set of example components that you are free to use (unsupported) or copy and adapt (they are provided under the Universal Permissive Licence 1.0).  When we originally released this feature we partitioned these example components into three component packs (see this blog article to learn about packs). Those packs where prefixed oj-sample, oj-sample-mobile and  oj-ext.  As time has gone by we've realised that there is really no value in managing each of these component sets separately and so we've consolidated all of the components into the base oj-sample pack.  The older packs, (oj-ext and oj-sample-mobile) are still available in the catalog but they will no longer be updated over time and the "newer" versions of the components are present in the oj-sample pack instead.  The following are the effected components and the names of the new versions: Deprecated Component Replacement oj-ext-checkbox-switch oj-sample-checkbox-switch oj-ext-export-data oj-sample-export-data oj-ext-export-utils oj-sample-utils oj-ext-highlight-text oj-sample-highlight-text oj-ext-input-email oj-sample-input-email oj-ext-input-url oj-sample-input-url oj-ext-metric oj-sample-metric oj-ext-utils oj-sample-utils oj-sample-mobile-online-detector oj-sample-online-detector oj-sample-mobile-orientation-detector oj-sample-orientation-detector oj-sample-mobile-pull-to-refresh oj-sample-pull-to-refresh   Currently both the old and the new components are visible from the cataog search, depending on the version of Visual Builder the deprecated ones (oj-ext-* and oj-sample-mobile-*) may be marked with a warning triangle to show that they are no longer compatible with the version of the JET toolkit being used by your version of Visual Builder.  For example from Visual Builder 19.4.3 if I search for "checkbox" in the catalog I will see both the old deprecated oj-ext-checkbox-switch and the replacement oj-sample-checkbox-switch. As you can see, Visual Builder is warning me that the oj-ext version may not be compatible.  A New Application - Choosing the Component to Use  Fairly obviously, if you want to try out one of these components, you should only use the oj-sample versions.  Once all public cloud instances of Visual Builder have migrated onto 18.4.3. or above, the deprecated components will actually be hidden in the browser so you won't be able to get this wrong.  they will still be there to allow existing applications to continue to run, but you'll not be able to accidentally add them to a new application.   For now, however, before installing the component, click on it to see the readme document for the component and make sure that it is the oj-sample version that you are installing (as per the table above). Migrating Existing Applications  If you have an existing application that uses any of the deprecated components you should move to the new versions at a convenient time.  The deprecated components will continue to function, however, they will not be updated any more and there is no guarantee that they will continue to work in future versions.  If you have installed a component into the component palette, but not actually used it in your application then you will simply be able to uninstall it from the browser. Just click the "Uninstall Component" button: However, if you have used the component then things are slightly more involved let's go through the steps. Note I have deliberately defined this set of instructions for use by someone who is not particularly familiar with working directly with the Visual Builder metadata so as to make the process as fool-proof as possible. These instructions are based on the use of Visual Builder 19.4.3 so I would not recommend embarking on that process until you are upgraded to that version.  Step 0 - Back up the Application It goes without saying that you should not start with these changes unless you have a backup that you can revert if you make a mistake. Step 1 - Identifying the Components You Need to Migrate  The step is very simple.  Visual Builder records the catalog components that you have consumed in a single place in the file <your app>/settings/dependencies.json. So switch the navigator to source view and navigate to that file: In this example we can see that the application "webapp" is using checkbox-switch and export-data from oj-ext and pull-to-refresh from oj-sample-mobile.  This tells us that the list of components to replace are: oj-ext-checkbox-switch oj-ext-export-data oj-sample-mobile-pull-to-refresh Step 2 - Installing the Replacement oj-sample Versions Now that we have the list of components to fix up, the next step will be to simply switch to the component catalog browser view and search for the replacement and install that. e.g. Search on the full name and click the entry in the browse panel so that you can confirm that it is indeed the one that you want.  Install as normal. Step 3 - Replace Usages Next we need to just switch any usages of the old deprecated version tags to the new oj-sample ones. The components themselves are drop in replacements so this is just a search and replace operation.  In Visual Builder 19.4.3 and above the Find In Files capability makes this trivial.  So for example we can search for "<oj-ext-" In this case We can see that just one page contains components that need to be changed.  We don't have to worry about the usage of the component name in the component IDs or <oj-label> for= attributes, just change any instances of the actual component tags (e.g. <oj-ext-checkbox-switch ...>) to the new name (<oj-sample-checkbox-switch ...>), not forgetting to do the closing tag as well (</oj-ext-checkbox-switch> -> </oj-sample-checkbox-switch>). Once you've updated the tags in the HTML code view , they will all be underlined with red squiggles for example: So once you have updated all of the tags on the page, hover over any one of them and choose "Add all missing dependencies for this page". The squiggles will disappear. For the same page open the page JSON file,  in the imports > components section of the metadata you will now see entries for both the old components that you have replaced and the new ones: "imports": { "components": { "oj-label": { "path": "ojs/ojlabel" }, "oj-ext-checkbox-switch": { "path": "oj-ext/checkbox-switch/loader" }, "oj-ext-export-data": { "path": "oj-ext/export-data/loader" }, "oj-sample-mobile-pull-to-refresh": { "path": "oj-sample-mobile/pull-to-refresh/loader" },     "oj-sample-export-data": {       "path": "oj-sample/export-data/loader"     },     "oj-sample-pull-to-refresh": {       "path": "oj-sample/pull-to-refresh/loader"     },     "oj-sample-checkbox-switch": {       "path": "oj-sample/checkbox-switch/loader"     } } } You can just delete the entries for the unused deprecated components so you might end up with just:  "imports": { "components": { "oj-label": { "path": "ojs/ojlabel" }, "oj-sample-checkbox-switch": { "path": "oj-sample/checkbox-switch/loader" }, "oj-sample-export-data": { "path": "oj-sample/export-data/loader" }, "oj-sample-pull-to-refresh": { "path": "oj-sample/pull-to-refresh/loader" } } } Step 4 - Clean up At the moment, the component palette in the page designer will be showing both the deprecated and the new components which will be confusing, so we can now clean that up. This will involve opening the <your app>/settings/dependencies.json file again (See Step 1). Simply remove the oj-ext and oj-sample-mobile entries from that file. e.g. in my case I'll end up with just the references to the oj-sample components:  { "component-dependencies": { "oj-sample": { "version": "3.1.2", "components": { "checkbox-switch": "3.0.0", "export-data": "3.0.3", "pull-to-refresh": "4.0.2" } } } } You may have other entries in here, so be sure to delete the packs for the deprecated components only.  Now switch to the Component Browser and you will be able to click on Uninstall Component button for each of the deprecated components. Once you have done this then component palette will only show the new oj-sample versions. Finally you can tidy up the app-flow.json file as well. Open it up and search for the requirejs > paths section.  It will look something like this:  "requirejs": { "paths": { "oj-ext": "build/components/oj-ext/2.2.3", "oj-sample-mobile": "build/components/oj-sample-mobile/3.0.0", "oj-sample": "build/components/oj-sample/3.1.2" } } You can just delete the entries for oj-ext and oj-sample-mobile as these are no longer needed. Leaving these paths in will not do any harm but they are now redundant so I recommend that you remove them.  Once you have completed all of these steps then you're done and you will be able to automatically receive future upgrades as we push them out.   

Introduction In Oracle Visual Builder we provide a capability to add additional custom components into the page designer component palette from a shared catalog. As part of this offering we...

Oracle Visual Builder Cloud Service

Using Backends, Servers and Application Profiles in Visual Apps

In the previous blog post we saw some basics of backends and servers, their definitions in the catalog.json file and how they work at the Tenant level.  It is worth reminding that the backend setup is only needed if you plan to create Service Connections from the out-of-the-box Service Catalog VB provides (currently supports Oracle Cloud Applications, Integrations and Process backends).  Service Connections created from endpoint or from a specification like Swagger/Open API dont need a backend setup, but the concept of servers for segregation of configuration applies to them as well.  In this blog post, we see some scenarios of backends and servers at the Visual Application level and how to wire them up corresponding to dev, stage or published versions of your app You can access the backend information for a Visual Application by navigating to (Visual Application) Settings -> Services.  Visual builder developers can access these settings for any Visual Application they have access to.  A snapshot of the Backend settings at application level is shown below Here, we have two servers for the backend "Integration Applications" (At the app level you can have multiple servers for a backend, unlike the tenant level, where you are restricted to only one server to one backend).  One of the server called "Overridden Integrations Applications Server" is pointing to the tenant backend and derives its URL from there, the other server called "Second Server" has an absolute URL. Similar to the tenant level, the backend and server settings at the application level are also represented in a catalog.json file at the application level which can be seen from the source editor.   Let's see the catalog.json behaviour with various cases at the Application level Backends and Servers at the application level CASE 1 - No application backends (Tenant backends may be present) This is the default case for a newly created application.  Navigate to VB application settings and click on the Services tab.  With backends defined at the Tenant level, but no backends at the application level, the screen should look like this A quick look at the source editor confirms that the catalog.json has no backend entries, which means, whatever backends are shown on the screen are being inherited from the Tenant settings   CASE 2 - Full Override of a tenant backend at the application level Let's override the "ics" backend.  Click the + icon near the backends list, which opens a dialog for choosing the backend type.  On choosing an Integrations type backend, a dialog to add relevant Server details appears.  Add these and click Create. Now you can see that the Integrations server list reflects the new server details and there is no connection to the Tenant backend at all.  Also there are a couple of things in addition to what we saw in the Tenant backend settings  "Override Tenants Settings" switch is in the ON position - this indicates that you have overridden the Tenant settings Additional field "Used in profile : Base configuration" is also present.   This tells you what application profile is the Server linked to.  Application profiles are a way to attach different configurations to the same backend ( for e.g. a test instance for Integration connections for testing purposes), so that your application can remain the same, but have different configurations based on which application profile you are using.  There is always a default application profile available in a Visual App (In this case it is called Base configuration).   The first server in the server list of a backend is the default server for this backend.  This means that any newly created application profile will automatically be attached to this server (we will see this later on in the blog).  The catalog.json now has an entry for "ics" with the URL and the other settings specified Note that there is no mention of an application profile for the https://int.oracle.com server as it is the default.  Therefore all profiles that are not explicitly linked to a server for this backend will automatically be linked to this server.   CASE 3 - Partial Override of a tenant backend at the application level Sometimes, we want the server URL same as that inherited from the Tenant backend, but certain settings need to be overridden. Let's see how this works. By default, the "Override Tenant Settings" will be off.  Click this switch to enable the override and you will get a changed entry in the server list called "Overridden Integration Applications Server 1" The difference in this approach is that there is still a link to the tenant's "ics" backend, and you can selectively override the things you want like authentication settings.   The URL now shown for the server is is vb-catalog://backends.tenant/ics.  The backends.tenant is a special entity to indicate that the URL resolution should happen based on the tenant's backend called "ics".   Click on the pencil icon to edit the server.  You can see some extra options available as shown in the above figure, namely A checkbox called "Override the configuration inherited from the backend"  which is by default checked- this indicates that the Authentication settings defined in the application's catalog.json take precedence over the Tenant's catalog.json.  The authentication from the tenant's backend is simply copied to the overridden server's authentication ("Oracle Cloud Account") An extra Connection type called "Inherit from catalog" - this indicates that the Connection type setting is the same as that defined in the server of the Tenant backend. The catalog.json now looks like below: There is an x-vb/authentication block, which means though the URL is inherited from the tenant's "ics" backend, the authentication is overridden and whatever is defined at the app level is used.  Currently there is no forceProxy setting (representing the relevant Connection Type) as the option selected is "Inherit from catalog" .  If you change this value, you will start seeing an overridden forceProxy value as well in the catalog.json. You can now add more servers and link them with different application profiles.   CASE 4 - Adding more servers to the Application backend Now that the Tenant settings are overridden, you can proceed to add more servers.  Lets add another server to the overridden "ics" backend.  For this, click on the + Server button, and fill in the relevant server details as shown below: You can see that a second server is now added to the list.  The catalog.json looks as below In our application there was just one application profile defined - Base configuration.  The catalog.json doesnt show any link of Base configuration to any of the servers for ics backend, though the UI shows the Base configuration linked to the first Server, and nothing attached to the second server.  Why is that so? The answer is, since we designate the first server in the list as the default server for that backend, and this gets attached to any application profile by default (unless the application profile is made to explicitly associate another server for this backend) Let's see what happens when we create another application profile - TestConfiguration.  For this, go to the Application Settings -> Application Profiles.  The Base configuration currently shows the "Overridden Integration Applications Server 1" for the ics backend. Duplicate the Base Configuration into the new application profile - TestConfiguration.  A quick observation of the Test configuration profile shows Both application profiles have the "Overridden Integration Applications Server 1" as the server, as this is the first server in the list for the "ics" backend. This can also be checked in the Backend List by navigating to the Services tab as below For associating the Second Server to TestConfiguration profile, we will edit the "Second Server" and add the relevant profile there as shown below. This will remove the "Overridden Integrations Application Server 1" from the TestConfiguration as well, as there can be at max one server attached to one backend for each profile.     This completes the discussion on application backends and servers.  Let us now see an example of servers and backends usage in an actual application. Application profiles Let's say our purpose is to configure our application in such a way that Development  version of the application refers to the first server (https://int.oracle.com) server and Stage refers to the second server (https://secondint.oracle.com) server for the Integrations Cloud backend.  (Note int.oracle.com and secondint.oracle.com are just dummy servers used as way of explanation here, you should connect these to relevant development and test instances).  We already have seen in the previous section how each server for the "ics" backend can be configured to use different servers attached to different application profiles.  Now we need to make the TestConfiguration profile to be used for the staged version of our app. For this navigate to Visual App -> Settings -> Application Profiles.  The application profiles should show both the ones we have created - namely "Base Configuration" and "TestConfiguration".  Click on Base Configuration and select the option to make it "Development default".  Similarly click on the TestConfiguration and select the option to make it "Stage default".    You show now see both application profiles as below. With this, the development and stage versions of the application should route to https://int.oracle.com and  https://secondint.oracle.com respectively.   Service Connections Let us now create a Service Connection based on "ics" backend. Create a new Service Connection, choosing the option of Create from Catalog.  Choose Integrations, and proceed to add any endpoint that is available in Integrations Cloud.  In our example, we have a simple REST resource DEMOBACKEND/getDemo which is deployed on both dev and test Integration servers, but returning a different string based on each of them.   Go to this newly created Service Connection.  There are different tabs like Service, Servers, Endpoints, Headers, Transforms, Source that give different details about the Service Connection.  Opening the Server tab shows us a Server list complete with the application profile information, that is simply inherited from the application level "ics" backends.   Note that there is no separate link for the two servers, but both have just one edit link.  This is because both come from the same backend "ics" defined in the application's catalog.json.  Clicking on the pencil icon, we can see that configuration for a Service Connection is similar to that of a backend with some differences Instance URL is vb-catalog://backends/ics/ic/api/integration/v1/flows/rest.  This basically resolves the Service Connection URL to the backends entity in current catalog.json (i.e. the application's catalog.json) ,  Depending on the application profile used, this will either be resolved to https://int.oracle.com or https://secondint.oracle.com A checkbox called "Override the configuration inherited from the backend"  which is by default unchecked - this indicates that the Authentication and Connection Type settings are inherited from whatever is defined in the backend.  You can choose to override the backend settings and define new ones here if needed. Application profile information - All the profiles that are resolved by these servers.   It is worth mentioning that you can add servers at the level of service connection too (rather than the backend), and associate them with different application profiles. This completes all our setup for configuring a Service Connection based on Integrations Cloud backend configured with a different server for development and stage. Running the application We can test application profiles by creating a small application which has a button that calls this Integration REST API and see how it behaves in development preview mode and with a staged URL.  The below screens show the output of such an app. With the preview mode of the application With the staged version of the application This blog took the example of an Integrations Cloud backend to show these examples, but the principle is same for other backends like Oracle Cloud Applications backend too. That completes this two-part blog on servers and backends!  If there are any questions, please leave them in comments.                      

In the previous blog post we saw some basics of backends and servers, their definitions in the catalog.json file and how they work at the Tenant level.  It is worth reminding that the backend setup...

Oracle Visual Builder Cloud Service

Visual Builder - Understanding Backends and Servers

Visual Builder 19.4.3 introduces the concepts of backends and servers to segregate information about types of resources and the actual server details the resource point to.  In this blog post, we look at the basics of backends, servers and how to configure them at the Tenant level.   A "backend" is a representation of a known resource like Integration Cloud, that Visual Builder understands.  A backend contains a list of "servers" to help connect to this backend.  Each server can be thought to encapsulate the details needed to connect to this type of resource like authentication, URL, etc.    Why do I need a different artifact to store this information rather than the Service Connection metadata?  If your purpose was to connect to REST APIs from the out-of-the-box Service Catalog, and avoid the hassle of settings URLs, authentication and all of that every time you create a new Visual application, a backend helps you to do just that.  Note that you can also create a Service Connection from endpoint or from specification where you dont strictly need a backend.  Simply speaking, backends are the way to reuse external REST Resource configuration across all applications.   OK, so why do I need multiple servers for a backend? Sometimes, you want the same application to connect to different URLs of resources to get data.  A common example would be you want the same application to connect to a development OIC (Oracle Integration Cloud) server while in development, but testers might want the application to be connected to a test OIC server while testing.  The segregation made between the logical backend (OIC) and the actual servers that consist of the connection details make this possible.   The Service Catalog is represented by an OpenAPI3 compliant file called the catalog.json, that contain all the backend and server information.  We can define backends and servers at the Tenant (or Instance) level as well as at the application level.  So there is a catalog.json file at the Tenant level and one at each Visual App level.  When you create a "Service Connection From Catalog", the catalog.json files are consulted to get a particular backend type's REST APIs.  A simple flowchart showing this in practice is shown below     We can access the tenant backends by going to Tenant level Settings -> Services which shows the Backend Editor as shown below.  (Note you will need to be an administrator to access the Tenant level Settings)   Here, the right hand side shows the details of a backend called "Oracle Cloud Applications" which has one server called "Default Server".  On clicking the pencil icon to edit the server, we can see more details about the server like below   The full catalog.json file is available by clicking the source editor icon on the right most side.  The pre-defined backends available in VB are : Oracle Cloud Applications (Fusion Apps), Integrations Cloud and Process Cloud.  Oracle Cloud Applications have the further sub types - Sales and Service, Enterprise Resource Planning and Supply Chain, and Human Capital Management.  These pre-defined backends are known by the following names in catalog.json   Backend Backend name ServiceType Oracle Integration Cloud (a.k.a OIC) ics ics Oracle Process Cloud (a.k.a Process) vbprocess vbprocess Oracle Cloud Applications (a.k.a Fusion Apps/FA) fa fa-base Enterprise Resource Planning and Supply Chain fscmRestApi fa Sales and Service crmRestApi fa Human Capital Management hcmRestApi fa   Here is a structure of a catalog.json, where a backend called "ics" is defined with two servers.  The first server in the list is the default server.  Each Server has a URL, authentication, connection type.  The second server also has an extra block called "profiles" which point to which application profiles (see more here) this server is attached to.  This enables us to configure a server for say, development activities, and another server, for testing activities separately. Note that though the catalog.json contains information about what kind of authentication is used (e.g. Basic), any credentials are safely externalized away from the catalog.json. Tenant backends have some restrictions  There can be only one server for each backend at the tenant level.  There are no application profiles at Tenant too. Limited authentication options are available for Tenant servers, namely None and Oracle Cloud Account/Propagate Current User Identity, which require that you either have a non-authenticated instance, or an instance with identity propagation configured between VB and the target instance (like co-hosted VB and Oracle Integration Cloud).  If you dont have a server that satisfies this, you can circumvent this limitation by defining backends at the application level, where all authentication options are available   Let us now see the VB catalog in action with the following cases  CASE 1 - No tenant backends Navigate to VB Tenant Settings and click on the Services tab.  If none of the backends are defined, you should see an empty list as below The corresponding catalog.json would have no backend entries   Note - you might have pre-configured backends if you have a co-hosted Visual Builder+Oracle Integration Cloud combination or if you have configured the Oracle Cloud Applications catalog before.     CASE 2 - Creating a tenant backend (if there are no backends of the type) You can only use an Integrations backend at the Tenant if you have a Oracle Integrations Cloud provisioned with Visual Builder.  In normal cases, this backend would have been auto-created during provisioning itself, and you are recommended not to change the settings Click on the + Backend button and proceed to create an Integrations Application backend.  Add the following details Instance URL Authentication for logged in users - typically Oracle Cloud Account Connection type - This tells whether the call from VB to the actual service should go via a proxy or directly.  More about Connection type can be read here  All other settings are optional Click on Save.  The new Integrations Application backend should be created as below   We can see that along with the backend ("ics"), the server that houses all the details for the backend is created as well and is now visible in the server list.  Note that you can only create one server for any given backend at the tenant level, so no options to add server is available.  If needed you can navigate to the headers tab and define applicable headers for this newly created backend.   There is only one backend of the given type.  On clicking + backend again, you will be shown a message that the backend already exists.   You can see the catalog.json representation of the newly created backend by clicking the Source Editor icon   Once a backend is configured, you can proceed to create Service Connections of this type from the Service Catalog. CASE 3 - Creating an Oracle Cloud Applications backend (if there are no backends of the type) Unlike the Integrations backend, this will not be auto-created, and you will need to configure this once you have federation setup with an Oracle Cloud Applications (Fusion Apps) instance (More details to achieve federation here) Click on the + backend button and proceed to add an Oracle Cloud Applications (Fusion Apps) backend.  When prompted to add server details, provide the following Instance URL - You need to have a valid Oracle Cloud Applications (Fusion Apps) URL for this Authentication for logged in users - typically Oracle Cloud Account Connection type - This tells whether the call from VB to the actual service should go via a proxy or directly.  More about Connection type can be read here All other settings are optional While creating this backend, there is some background processing done by VB.  First VB fetches the interfaceCatalogs URL ( i.e. <Oracle cloud apps base URL>/helpPortalApi/otherResources/latest/interfaceCatalogs ) for the particular instance and discovers information about the sub-pillars of this instance like CRM, ERP and HCM and then proceeds to fetch the minimal describe URL for the instance.  Based on the information retrieved, the sub pillars or sub-backends for CRM, ERP, HCM will be automatically created as well.    Navigate through the backend tree to browse the sub-backend of "Sales and Service".  These sub-backends have a derived URL from the main backend in the form of vb-catalog://backends/fa/<sub pillar type>/resources  Navigate to the "headers" tab.  You should be able to see the Rest-Framework-version header also automatically setup for the newly created backend.  This header is based on the allowed version of REST framework for the Oracle Cloud Applications instance that was provided   CASE 4 - Overridding a sub-backend at the Tenant  Let's peek into the Server details of "Sales and Service" sub-backend created in the previous case.     We can see the following things dependent on the main (Oracle Cloud Applications) backend: The URL pointing to vb-catalog://backends/fa/crmRestApi/resources - this tells VB to look in the current catalog.json for a backend called "fa" and append "/crmRestApi/resources" to it.   REST-Framework-version header which appears as an inherited non-editable header Authentication and Connection type information - (which is not shown at all) in the right hand side To override the Sales And Service backend to point to some other URL for all the applications, we edit the value to the URL to point to an absolute (HTTPS based) URL.  This dissociates the link between the Sales and Service backend and the parent Oracle cloud applications backend.     Alternatively, we can choose to override parts of the server like the header values and the Authentication and Connection type information For overridding the header we simply define another header with the same name and give it the desired value For overridding the Authentication and Connection type information, we tick the checkbox marked "Override configuration inherited from the backend" Below, the header is overridden to have a value of 3 and the authentication and connection type information is also changed from what is defined at the parent backend.     CASE 5 - Process Backends Process backends are automatically created at the Tenant level when you provision  the Enterprise edition of Oracle Integration, which includes the Processes and Oracle Visual Builder features.  In normal cases, you will not need to update this information.  These are not used to define Service Connections, but are used when you access Process related tasks in Visual Builder,  To know more about Processes, and how to leverage them in Visual Builder, refer to this documentation    That's it for this post.  Next time, we dive into more detail and take a look at Backends at application level.                          

Visual Builder 19.4.3 introduces the concepts of backends and servers to segregate information about types of resources and the actual server details the resource point to.  In this blog post, we look...

Oracle Visual Builder Cloud Service

Simplified Test Driven Development With Oracle Visual Builder

A unique new capability of Oracle Visual Builder, added in the March 2020 release, is streamlined creation of tests for action chains. With this capability developers can easily define test cases for business logic and run them to monitor their app and identify code changes that break functionality. Visual Builder helps by removing the need to manually code the test cases, instead generating possible test result suggestions that can be added to test suites. In addition Visual Builder reports the percentage of code coverage for the tests that developers create. With these new capabilities test driven development becomes much more approachable to everyone as you can see in the demo video below. TDD - A Good Practice, Not Often Used Test Driven Development (TDD) - is the practice of defining expected results from your business logic, and then making sure those results are matched whenever your code (or code you depend on) changes. Incorporating tests into your development cycle helps identify breaking code-changes earlier, making it easier to detect the offending code and fix it. Overall, test driven development results in better and more stable applications. Despite the proven benefits of TDD, many developers skip the creation of tests since this can be a tedious task, preferring to focus their efforts on other tasks. The new test generation capabilities of Visual Builder are aiming to remove such roadblocks and help your team adopt TDD. Visual Builder - To the Rescue A new "Tests" tab is available in the action chain area of Visual Builder where you can define your tests and execute them. Visual Builder automatically identifies the variables that the action chain depends on, and prompt you to specify sample data for them. VB also identifies REST calls that are part of your chains, and provides the ability to define mock samples that represent responses from those calls. Visual Builder then automatically provides you with suggestions for test results you can evaluate. Visual Builder does this by simulating the execution path of your logic based on the input you provided.  You can then pick up these suggestions and add them to your test definition, as you do this Visual Builder gives you a visual indication of which parts of your business logic have tests defined for them (turning the icons in the diagram blue). Multiple tests can be defined for each action chain, using different combinations of values for variables and REST calls to get alternative test results. This way you'll build a set of tests for your action chains that will cover all the possible results you expect to get. You can run an individual test or all the tests - and get a report on the success rate and any failures will be highlighted. While you are defining your test cases, Visual Builder keeps track of your code coverage. Any point in the action chain that is covered by a test will turn blue, until you achieve 100% code coverage. This helps you eliminate situations where you have untested code in your business logic. In the video below we show you an example scenario of creating multiple tests for an action chain in an application that involves variables, REST calls, and JavaScript functions. Check it out:

A unique new capability of Oracle Visual Builder, added in the March 2020 release, is streamlined creation of tests for action chains. With this capability developers can easily define test cases for...

Oracle Visual Builder Cloud Service

New Features In Oracle Visual Builder - March 2020

The Visual Builder team is happy to announce the rollout of a new version of our service with many new features and enhancements. In this blog entry we highlight the key new additions, but you are certain to discover many other enhancements as you go through your daily development process as well. Action Chain Test Automation We all know that following a test driven development approach can help detect coding issues sooner, making it easier to produce a fix. So how come not all developers follow this methodology? Maybe because writing tests for your code is not fun. With the new Action Chains Test Automation features Visual Builder makes test creation easy and painless. Visual Builder looks at your action chain, and automatically suggest helpful information for defining tests. All you have to do is provide examples of values you expect in variables, and typical results from your REST calls, and VB runs through your action chains and offer suggestions for test results you might want to add to your test case. You'll also be able to see what percentage of your code is covered by your test, and be able to run individual or complete test suites easily. Application Profiles When Visual Builder applications access data from other sources, it is quite common to have different backend environments used for the development, test, and production stages. With the new application profiles feature in VB, you can define combinations of different servers and security settings to be used in each stage of your application. These profiles will be picked up when you move your application from dev to stage to publish and applied properly. You can also use the same profiles when you automate your application's CI/CD through the VB grunt lifecycle commands. Further simplifying this switching is the introduction of two new artifacts - backends and servers. Backends - are types of servers you connect to such as Oracle Cloud Apps, Oracle Integration Cloud, and Oracle Process Cloud. The other artifact is called a server - which is constructed from a combination of URL, headers, authentication, and connection settings for a specific server. This allows you to easily switch the server being used as a specific backend in your application when using a specific application profile. Open API 3.0 Support Open API 3.0 is becoming the de-facto industry standard for describing REST based services through metadata. Up until now VB supported Swagger - the predecessor to Open API. With this release Visual Builder adds support to import Open API 3.0 meta-data to help help you consume REST services easily. Improved REST Service Connection Options We've redesigned our REST service definition dialogs to streamline the process of adding REST services to your app. We've also made it easier to understand how to connect to different services in terms of security settings, CORS support, and usage of the Visual Builder Proxy.  In addition, we added support for connecting to resources on Oracle Compute Infrastructure (OCI) using the API signature approach. We also made it easy to specify headers and assign them to specific servers. You'll notice UI improvements all over the service connection dialogs, as well ass the ability to switch to code view to see the service's metadata directly. Easier Component ID manipulation In the new release we exposed the ID attribute of UI components in the Property Inspector - so you can see or modify it quickly. This is quite handy when you later want to refer to the component from action chains, either through a call component method action, or from your JavaScript code when you try to access the UI component. By the way, if you decide to change the ID after you already referred to it from action chains, VB is smart enough to refactor the ID across those places too. Find in Files While on the topic of refactoring across the app, a new "Find in Files" tab allows you to find all the references to a name in the app, so you can refactor all of them more easily.  New Mobile Capabilities To help you further leverage the devices you are running your apps on, the Open URL action allows you to easily access files and open them with dedicated mobile apps.  Two new $application level variables ($application.deployment.appType & $application.deployment.pwa) distinct between applications that are web vs mobile and whether they are packaged as PWA. This can help you better tailor your app behavior while reusing code in the app. Mobile app also benefit from the new Application Profile features mentioned above. JET 8.1 Support We've updated Visual Builder to pick up the latest version of Oracle JET, including new UI components, and, of course, any bug fixes and enhancement that were included in the releases since JET 7.1. You'll also notice new UI components in the Component Palette including treeView and heatMap visualizations. Business Object Resource Editors When you build large data models made up of many inter-related business objects, the service definitions for these business objects can become bloated. This is because, by default, Visual Builder generates a complete set of accessor REST APIs at every level of the relationship between objects.  We've introduced a new Business Object Resource Editors which allow you to tailor exactly which relationships are exposed by REST endpoints and which aren't, thereby maximizing the performance of your apps both at runtime and when using the designer. Wait There's More The features we listed above are by no means a complete list of new features. You should visit our "What's New" document to learn about other features and to be able to directly navigate for the new documentation on the features we added. Let us know what you think by commenting on the blog or on the Oracle Visual Builder Community.  

The Visual Builder team is happy to announce the rollout of a new version of our service with many new features and enhancements. In this blog entry we highlight the key new additions, but you...

Obtaining All Rows from a REST Action using Recursive Action Chain Calls

Introduction  This article introduces a standard pattern that can be used to achieve the goal of obtaining all rows from a REST endpoint when that endpoint only supports a paging API.  What do I mean by a paging API? Well that's the case where there is no option to just ask the endpoint for all rows at once but instead you have to pass it (or it will assume) some fixed number of rows to fetch per call.  An example is the pattern used by Visual Builder Business Objects and ADF Business Objects exposed through REST that have a URL pattern like this:  <some endpoint>?limit=25&offset=0. Meaning start at row zero and give me 25 rows. The return payload will then typically include a flag e.g. hasMore, which tells you that there are more rows available, in which case you would need to issue another call to get the next batch of rows, starting from where you last left off e.g. <some endpoint>?limit=25&offset=25 and so on, until hasMore=false. Of course REST APIs differ and if the endpoint has a flag to ask for all the rows at once then just use that, but let's stick to how to implement this recursion for the core Visual Builder Business Object case.  The Scenario  For the sake of illustration I'll be using a Business Object called Participant with an id field and an email field and my final goal is to fetch all of the emails into a single array variable in the page.  Implementing the Pattern Step 1 - Defining Types To keep your code readable and maintainable, I strongly encourage  the liberal use of well defined types to make mapping clearer and less error prone.  For my use case, the Participant Business object exposes a GET many endPoint for which we'll want to generate a type, and I'll also create a simple object for the array row type called emailRecordType:   Step 2 - Defining the Destination Array I'll need somewhere to store all the data, so I create a page variable called emailArray with an Array type and an Array Item Type of the emailRecordType defined above.  Of course this variable will initially be empty.  Step 3 - Define the API for the Recursive Action Chain  As the title of the article mentioned, the process of making multiple calls to the endpoint to get all the rows will be managed through recursion, e.g. I'll have an action chain that will call itself, essentially looping until all the rows (or some max number of rows) have been obtained.  So the first part of this will be to define the API for that Action Chain in terms of the inputs to it and the data that it will return.  So I create a new Action Chain called fetchBatch and define input parameters and a return type as follows: Some details on each of those input parameters: accumulator - this will be used to pass the set of data pulled from the endpoint to the next iteration of the loop / recursion.  It has a default value of an empty array ([]) fetchBatchSize - is a number input which can be used to define how many rows to get from the endpoint on each iteration.  I've defaulted it to 25, but you can set that to whatever works best for your use case.  maxRows - is a number defining an approximate maximum number of rows you want to get before stopping. This is just a bit of a safety net and optional.  I've set it to a default value of 1000. startFetchFrom - is a number defining where to start a given iteration from. This value will increment by the fetchBatchSize as we go through each iteration.  The default is 0 (zero) as we want to start at the beginning! The return type for the Action Chain is again an array of the emailRecordType I defined in step 1. Step 4 - Define the REST Action  Now we need to implement the Action Chain and the first step is the actual call to get a batch of records.  To do this. we just drop a Call REST Endpoint action into the flow and wire that to the endpoint that I'm getting the data from:  And let's look at that assignment mapping in more detail: You can see here that the fetchBatchSize and the startFetchFrom input parameters are mapped to the limit and offset parameters on the REST call. In this case I've also set onlyData (to true) and the fields that I want in the return payload to optimize things a little, but that's optional. The return type for the REST action is the getall_Participant type that was set up in step 1. Step 5 - Save the Results of this Batch The next action to add to the chain is one to assign the returned email addresses into the accumulator array. This just uses an Assign Variables action with the following mapping: Notice how the Reset Target for the array assignment is set to none. This is important otherwise the accumulator won't do it's job! Step 6 - Do We Need to Recurse? Next we drop an If action into the Action Chain.  This will do two things for us: Check to see if the endpoint is reporting more rows are available (looking at the hasMore value on the REST response) Check to see if we've reached or exceeded the defined maxRows value The actual condition used in the IF is: [[ $chain.results.callRestChunked.body.hasMore && $chain.variables.accumulator.length < $chain.variables.maxRows ]] Step 7 - Do It All Again! If the recursion check passes then this is the point at which we need to recursively call the same action chain. To do this, we drop a Call Action Chain action in and map it to use this same chain.  The important part of course is is the mapping of the parameters: It's all pretty simple 1-1 mapping except for the value passed into startFetchFrom which of course needs the incremented fetch starting position which we can calculate as shown here by just adding the batch size to the previous start point. Step 8 - Remap the Updated Array Recursively calling the Action Chain will of course result in additional rows being added to the accumulator, so on our way back up the recursion stack we need to pick up that update.  So we drop another Assign Variables action in after the Call Action Chain and re-assign the output of the recursive call back to the accumulator.  Important! Notice that this time we set Reset Target to empty. If this was not done, the final array would include duplicated data (Just think about the logic of the recursion for a second and you'll get it). Step 9 - Return the Result With that we're all done. All we need to do now is return the accumulator array to the caller, so we drop a return action in and do so: And here's an overview of the whole chain that has just been defined: Once this chain is defined you can then just call it from your desired action chain and the recursion will take care of the rest., for example:

Introduction  This article introduces a standard pattern that can be used to achieve the goal of obtaining all rows from a REST endpoint when that endpoint only supports a paging API.  What do I...

Business Objects

Switching Visual Builder to Use The Oracle ATP Database

Oracle Visual Builder comes with a built in database that is used to store data for your business obejcts (and your apps metada too). That DB, however, is limited to 5GB in size and also doesn't enable you to access the data in the objects using regular SQL. Luckily, you can point Visual Builder to use another Oracle cloud database including the new Oracle Autonomous Transaction Processing (ATP) database - which will give you more space and direct SQL access to the objects VB creates. You can even use a Free Forever Oracle ATP which will get you 20GB of storage for free. In the demo below we show you the steps to take to do this switch. The switch over is quite simple and is done with a simple two step wizard in your VB instance settings. You'll need to provide the connection information to your DB - for an ATP DB this would include the wallet.zip file with the connection info. VB will then do the work for you switching to use the new instance. More info on the process is in our Visual Builder Administration Guide. One additional step you will need to do in the wizard is to backup (export) any apps you want to keep around. (Important note - if you have live applications already on the instance before migration - make sure to backup the data in their business objects using the export options in the Visual Builder data manager. You'll then be able to import that back into the new apps you'll create from your backup). Post Switch Visual Builder automatically manages the schemas and tables it uses for apps and business objects in your new DB - so you don't need to do anything further. If you would like to access the business objects using SQL, you'll find that VB creates users/schemas with names starting in VB_ followed by randomly generated strings. With a bit of inspection in the data dictionary you'll be able to find the users that represent specific apps. Note that you'll see separate schemas for dev, stage, and published instances of an app. The schemas for the dev and test instances will be re-created with different names with every new version of the app that you'll create. The schema name for the published app can stay fixed if you indicate to not replace the data in it when publishing new versions.  Here is the flow of steps in a quick video:

Oracle Visual Builder comes with a built in database that is used to store data for your business obejcts (and your apps metada too). That DB, however, is limited to 5GB in size and also...

Oracle Visual Builder Cloud Service

Ensuring Unique User Input in Oracle Visual Builder

A common requirement in most systems is the ability to ensure uniqueness of some attributes of a data record. Most of the time this will apply to record keys that perhaps managed behind the scenes either by your REST backend or by the built-in Business Objects layer in Visual Builder.  However, on some occasions we may want to apply similar uniqueness constraints to user-entered information as well.  In this article I'll be looking at both the declarative way your can do that when using Visual Builder Business Objects and then a more advanced technique can can be applied no matter what the backend is. Uniqueness Checking for Free When using Business Objects in Visual Builder, one of the basic declarative features of the field definitions is the ability to apply a uniqueness check at the database level. You simply do this by checking the Unique Constraint when defining the field.  Job done, the power of the Oracle Database kicks in and no more duplicates! If you now create a default UI to create a record in that Business Object you'll simply not be able to create a duplicate. However, there's a catch (of course or this would be a short article). In order for the user to see that there was a problem with their data they have to send the record to the server at which point that whole process will fail and the user will have to amend the data and try again.   What I'l like to do is have a validator that tells me there's a problem with the value that I've entered, before I try and save the record. And that's what this article is really all about.  Asynchronous Validation to the Rescue I've used the word asynchronous here and that's important.  By definition, in order to check that a value is truly unique we will need to go back and ask the server, and a trip back to the server is always going to be asynchronous. The Oracle JET toolkit, on which Visual Builder is based, just so happens to support asynchronous validation, so let's see what that looks like and how it can be applied in this situation.  Here's my starting point, I have a simple UI for registering band members and I want to ensure that whatever name is entered for the player is not already used by someone else in the band - just to prevent confusion in the fan-base.  The Player Name is an <oj-input-text> with the required attribute already set.  To add the validation I'm also going to set the async-validators attribute of the tag.  In Visual Builder you will find this on the All tab of the property inspector.  This property of the component takes an array of zero or more validators that are crafted in a slightly special way using JavaScript promises in order to produce the asynchronous background checking.  Unlike the normal validators array on input-text we can't define everything in-line in the property, just because we're going to write our own validator here, rather than using one of the pre canned validations. So, before we set that async-validators attribute on the tag, we'll need to write some code in the page module to create the validator in the first place.  About Asynchronous Validators Asynchronous validators in Oracle JET have pretty much the same API as normal synchronous validators except that the the API calls have to return JavaScript Promises which, when resolved (or rejected) will determine the validation state.  The API consists of one function and an optional property: validate method - this is called with the value that needs to be checked. If the promise that it returns is resolved then the validation has passed, if it rejects then the vaidation has failed and the payload of the reject call is the error message to display to the user.  hint property (Optional) - this hint is added as help to the UI to inform the user about the validation in question. Again this requires a promise to be returned and the resolved payload  must will be the hint text.  Because this hint message is also asynchronous you can use calls to the server to generate that as well (for example to tell the user up-front that certain options will not be available).  A Basic Asynchronous Validator So let's start with the most basic implementation of such a validator that we can use as a testbed - I'll evolve this later on to actually talk to the server to do a real check.  In the pageModule we need to create a function which will return an array of these Asynchronous Validators. For clarity I've split this into two functions, one (ayncValidatorsForPlayerName) to create the array to pass to the <oj-input-text> and a second (createNameCheckValidator) to create the actual validator.  In principle we can attach multiple asynchronous validators by adding more entries to the array returned by ayncValidatorsForPlayerName. define([], function() { 'use strict'; var PageModule = function PageModule() {}; PageModule.prototype.ayncValidatorsForPlayerName = function(){ var validatorArray = []; validatorArray.push(this.createNameCheckValidator()); return validatorArray; } PageModule.prototype.createNameCheckValidator = function(){ return { validate: function(value){ return new Promise(function(resolve, reject){ setTimeout(function() { if (value === 'Duncan'){ resolve(); } else { reject({detail:"The fans won't like "+ value}); } }, 1000); } ); }, hint: Promise.resolve('Choose a name that the fans can identify with') }; }; return PageModule; }); This first example only has a "fake" validation using a time delay of 1 second to prove the principle that it a) works and b) is asynchronous. To break down the code a little let's look at the createNameCheckValidator function.  This just returns an object with two attributes; The validate function itself  which as you can see checks that the entered name just matches a particular value and if so calls resolve(), if not it calls reject() whilst passing an object containing a detail attribute with the required error message. The second (hint) attribute does not need to be asynchronous in this case although it still needs to be a promise, so we use the shortcut of just create a pre-resolved promise with the message we want to pass as the hint text. So let's wire that up to the input field: <oj-input-text async-validators="[[ $page.functions.ayncValidatorsForPlayerName() ]]" id="oj-input-text-2091532825-1" label-hint="Player Name" required="true" value="{{ $page.variables.player.playerName }}"> </oj-input-text> So you can see here that I'm calling the ayncValidatorsForPlayerName function directly to grab the array of asynchronous validators. You have to type this expression manually into the PI field or code view as the property inspector does not provide a picker for functions -  so be careful and remember to include the parentheses to ensure that the function is actually executed as opposed to passed as a reference. Once wired up, we can test it. Here I've entered an "Invalid" value and we can also see the effect of the hint: Calling a REST Function from Your Asynchronous Validator Now that we have wired up and tested the basic principle let's move on to doing something realistic that involves calling a RESTful backend to check the proposed value against the list of names that have been registered already.  This uses a technique that I've discussed before in a different context: the REST Helper API. This API is the same one that is used in Action Chains to make REST calls and we can use it directly from our validator code.  Here's the amended version of the Page Module which shows this.  define(['vb/helpers/rest'], function(Rest) { 'use strict'; var PageModule = function PageModule() {}; PageModule.prototype.ayncValidatorsForPlayerName = function(){ var validatorArray = []; validatorArray.push(this.createNameCheckValidator()); return validatorArray; } PageModule.prototype.createNameCheckValidator = function(){ return { validate: function(value){ return new Promise(function(resolve, reject){ var endpoint = Rest.get('businessObjects/getall_Player'); endpoint.requestTransformationOptions({ filter: {criteria: [{ attribute: 'playerName', op: '$eq', value: value}]}}); var resultCallback = endpoint.fetch(); resultCallback.then(function(payload){ if (payload.response.status === 200){ if (payload.body.count > 0){ reject({summary:'Sorry cannot use ' + value, detail:'This name is already in use, try another'}); } else { resolve(); } } }); } ); }, hint: Promise.resolve('Choose a name that the fans can identify with') }; }; return PageModule; }); To examine the differences: The define() block now imports the vb/helpers/rest class under the alias of Rest.  This is what allows us to make calls to defined service endpoints Inside the Promise creates for the validate function we use Rest.get() to get a reference to the endpoint we want to query (this must already be mapped as a service or Business Object in Visual Builder, you can't use a URL here directly).  This approach looks up the correct endpoint information for you and takes care of applying any authentication if required. I setup the filter that I want on the endpoint.  How you do this will vary depending on the service, but in my case I'm using a Business Object so I can express this in exactly the same way as I would in an action chain or and Service Data Provider definition. In this example, to check for uniqueness I'm asking for any rows that match the requested value already.  Next we call the fetch() function on the endpoint which makes the asynchronous call and provides ne with a promise to wait on for the result. In the then() function of the callback promise we can check the actual results. In this case, if there is more than zero instances of the value then that shows that this would be a duplicate and so we call reject Notice that the reject call in this case is passing a summary as well as a detail value to provide an improved error message. With this new version, here's the result:  Hopefully you'll find this pattern to be useful.  If you are using Business Objects as your backend then I'd still recommend switching on the field level unique flag to ensure data consistency in cases where multiple users make simultaneous changes.

A common requirement in most systems is the ability to ensure uniqueness of some attributes of a data record. Most of the time this will apply to record keys that perhaps managed behind the scenes...

Distributing Visual Builder iOS apps - What you need to know

Developing a mobile app in Visual Builder is straightforward As a hybrid development environment you can develop and test your app using simulators for both iOS and Android and create runtime artifacts. But if you want to distribute an iOS app you need to think about your users and join the appropriate Apple Developer program. It is the program that provides the signing credentials you will need to sign and distribute your app. Apple provides a number of programs for the distribution of apps, but which is right for you? For an Enterprise, the answer is likely to be either the Apple Developer Enterprise Program or the Apple Developer Program or both. Essentially the difference between them is that the Enterprise program’s primary function is the development and distribution of apps within an enterprise. The Developer program (sometimes called the Standard program) provides for the release of apps to the Apple App Store. In both programs up to 100 devices (of each product family) can be registered per annum*. These are available when debugging using a Developer profile.  They are also used for testing using an Ad-hoc Distribution profile. This can be a restriction for larger development groups with distributed teams and 100+ devices. If a developer is using a developer profile in xCode and has a device attached to a MAC the device is automatically registered and the 100 limit can be quickly reached. Unfortunately deleting devices only removes them from the program once annually. This restriction is somewhat offset by using the Enterprise program. In addition to Developer and Ad-hoc profiles, the Enterprise program provides for the creation of InHouse Distribution profiles. The advantage of using this type of profile is that it is not tied to registered devices or developers. An app built with this profile can be installed on any device (but restricted to your enterprise). So InHouse Distribution profiles can be utilized during development and testing. If you have an AppleID you may have heard of Personal Team. If you’re developing using Xcode natively then it is possible to build and install your iOS app on your personal devices without membership of an Apple Developer program. But this is very restrictive both in respect of the limited number of features (eg no CloudKit, APNS), the number of apps you can install and the time they remain active on your device. If you are using Visual Builder you need membership of a developer program in order to access profiles and certificates to build and sign your apps. So back to distribution. For an internal-only app you’re likely to choose the Enterprise program. With this program you can create InHouse Distribution profiles that allow your app to be distributed either manually or through your EMM/MDM solution with no restriction on the number of devices that the app will load on. Part of your Enterprise program agreement with Apple mandates that you only distribute your apps within your Enterprise. The Enterprise program provides no testing environment - your organization needs to have process in place to manage its membership of the program and the distribution of signing credentials as well as versioning and management of apps. For an iOS app that is to be released to the public or B2B you have to use the Standard program. In fact you could also use it to distribute your app internally (B2Self). In addition to the Developer and AdHoc profiles for dev and testing, you build your app for store with an App Store Distribution profile. This version of the app is then uploaded to App Store Connect (note, it cannot be installed directly on a device). On upload your app is signed (again) and managed by Apple. To test this build you use the Standard program’s TestFlight feature: Designate internal and external ‘testers’ to download and install the app from store for testing for 90 days.  For those B2B, B2Self or custom apps that need to be restricted to certain partners/customers you utilize the Apple Business Manager or Apple School Manager within App Store Connect. For internal users the benefit of using App Store Connect for distribution, rather than your Enterprise program, might be the automatic version and management that this program offers. This video, from WWDC 2019, is a good explanation of all the options I’ve described above, plus it discusses the options for distribution when you are developing for a Third Party. In short, you should be a member of the third party’s developer program. You should not develop the app using your own developer program credentials. Armed with this information about the Apple Developer programs you should be able to continue the development and distribution of your Visual Builder iOS apps. *Unless you have negotiated a different arrangement with Apple Apple - Choosing a Membership

Developing a mobile app in Visual Builder is straightforward As a hybrid development environment you can develop and test your app using simulators for both iOS and Android and create...

Oracle Visual Builder Cloud Service

Getting Started with ORDS and Oracle DB/ATP Access in Oracle Visual Builder

Many of our customers are looking to expose data from existing Oracle databases in Visual Builder applications. In order to do this, you'll need to expose a layer of REST services on top of the database so Visual Builder could access and manipulate the data. One approach for doing this is to use ORDS (Oracle REST Data Services) - which provide a declarative way to achieve such exposure. In this blog we'll show you some of the basics of creating this connection. {Update June 2020 - You can improve the integration between ORDS and VB with the new OpenAPI support covered in this blog} In the video below we cover a simple flow from creating the table to exposing it with ORDS and consuming in Visual Builder. The first step is to expose a table through REST services, SQL Developer provides a nice wizard to help you achieve this. Simply right click a table and choose to REST enable it. When you do this you'll also choose the endpoint name for this specific table. Once you have that end point, you'll usually append it to a URL that has your DB Server name followed by ords/schemaName - so something like: https://yourDBServer/ords/yourschema/yourtable/ In Visual Builder you can add this endpoint in the service connection wizard - you can then define multiple endpoints that will map to each one of the REST operations such as GET, POST, DELETE etc. Once you have the GET operation you can hook it up to your pages and for example base a table on it - as shown in the video at : 2:00. Transform Functions The ORDS services have built in capabilities to do advance functionality including operations such as query by example, sorting, and pagination (fetching x amount of records at a time). You'll need to tell Visual Builder how to use those - and the way to achieve this is through the transforms tab in your service definition. Transform functions let VB know how to transform the info generated from filterCriterion, sort and pagination to the format expected by the REST service you are calling. When you click the checkbox, we'll create a sample piece of code that you'll need to adapt for your specific REST service. Once you define such a transformation VB will know how to do more advance things with your service - for example filter a serviceDataProvider variable using the filterCriterion approach and sort and paginate a table based on this ServiceDataProvider. The transform functions are generic for ORDS and don't depend on a specific table or service. Below I'm including the transform function I used in the video (which was developed by David Konecny from our VB team). Note that it doesn't cover all the operations available in filterCriterion - so you might need to add some code in there to handle other operators (around row 29). define(['urijs/URI'], function (URI) {     'use strict';       var Request = function () {     };       /**      * Filter transform function      * @param configuration      * @param options the JSON payload that defines the filterCriteria      * @returns {object} configuration object the url looks like ?filter=foo eq 'bar'.      */     Request.prototype.filter = function(configuration, options) {         var filterCriterion = options;         if (filterCriterion === undefined) {           return configuration;         }         var operation;         var criteria = filterCriterion.criteria;         if (criteria === undefined || criteria.length === 0) {           if (filterCriterion.attribute && filterCriterion.op && filterCriterion.value) {             criteria = [filterCriterion];             operation = "$and";           } else {             return configuration;           }         }         function jetFilterOpToScim(fop) {             switch (fop) {                 case '$co':                     return '$like';                 case '$le':                     return '$lte';                 case '$ge':                     return '$gte';                 default:                     return fop;             }         }           function isEmpty(val) {             return (val === undefined || val === null || val === '');         }           if (filterCriterion && criteria && criteria.length > 0) {           var q = [];           criteria.forEach(function(crit) {             if (crit.value === undefined || crit.value === '%%' || crit.value.length === 0) {               return;             }             var v = {};             if (crit.op === '$co') {               v[jetFilterOpToScim(crit.op)] = '%'+crit.value+'%';             } else {               v[jetFilterOpToScim(crit.op)] = crit.value;             }             var vv = {};             vv[crit.attribute] = v;             q.push(vv);           });           if (q.length > 0) {             var query = {};             if (operation === undefined) {               operation = filterCriterion.op;             }             if (operation === undefined) {               operation = "$and";             }             query[operation] = q;             // ORDS query URL is for example:             // ...ords/hr/emp?q={"$or":[{"ename":{"$like":"%david%"}},{"job":{"$like":"%developer%"}}]}             configuration.url = URI(configuration.url).addQuery({ q : JSON.stringify(query)}).toString();           }         }           return configuration;     };       /**      * Pagination function appends limit and offset parameters to the url      * @param configuration      * @param options the JSON payload that defines the pagination criteria      * @returns {object} configuration object.      */     Request.prototype.paginate = function(configuration, options) {         var newUrl = configuration.url;         if (options && options.size) {           newUrl = URI(newUrl).addSearch({limit: options.size, offset: options.offset}).toString();         }         configuration.url = newUrl;         return configuration;     };       /**      * Sort transform function      * @param configuration      * @param options the JSON payload that defines the sort criteria      * @returns {object} configuration object. the url looks like ?orderBy=foo:asc      */     Request.prototype.sort = function(configuration, options) {         if (Array.isArray(options) && options.length > 0) {             var firstItem = options[0];             if (firstItem.attribute) {                 var dir = firstItem.direction === 'descending' ? 'DESC' : 'ASC';                 var newUrl = configuration.url;                 var sort = '"$orderby":{"'+firstItem.attribute+'":"'+dir+'"}';                 var query = URI(newUrl).search(true);                 if (query.q) {                   query.q = '{'+sort+','+query.q.substr(1);                 } else {                   query.q = '{'+sort+'}';                 }                 // ORDS sort URL is for example:                 // ...ords/hr/emp?q={"$orderby":{"sal":"ASC"}}                 // BUT: sorting is applied after filter() method above so sorting                 // needs to be inserted into existing q param if filtering is on                 newUrl = URI(newUrl).search(query).toString();                 configuration.url = newUrl;             }         }         return configuration;     };       var Response = function() {       };       /**      * Paginate Response Transform Function Implementation      */     Response.prototype.paginate = function(result) {         var tr = {};           if (result && result.body) {             var cb = result.body;             // ORDS does not support "totalCount" but only "hasMore"             tr.hasMore = cb.hasMore;         }         return tr;     };       return {         request: Request,         response: Response    }; }); Some other things you might need to take care off are - having a valid SSL certificate for your ORDS - we have a blog that covers this here. You will also need to decide how are you securing your ORDS and providing authentication - for example using OAuth2.

Many of our customers are looking to expose data from existing Oracle databases in Visual Builder applications. In order to do this, you'll need to expose a layer of REST services on top of...

Oracle Visual Builder - New Features - Sep 2019

We are happy to announce the roll out of the latest version of Oracle Visual Builder - version 19.3.1 - which contains many new features in every area of the service. In this blog entry we are going to highlight some of these new features - but for a fuller list see our "What's New" documentation. Here are the key new capabilities: Bring Your Own Database You can now point Visual Builder to an existing Oracle Database in the cloud which will be used to host the tables maintaining the data for business objects created through Visual Builder. This allows you to store larger capacity of data (beyond the 5GB limitation that exist on the embedded DB in VB). Since the tables are created in your own database - you can also access them directly using SQL and do DML operation from outside VB. With the introduction of the new "Free Forever" layer of Oracle's cloud services you can get a free 20GB Autonomous Transaction Processing (ATP) database instance and point VB to use it. Improved Code Editor While Visual Builder is focused on giving you a visual approach to create your applications, one of the key benefit it provides is direct access to the actual HTML code of your pages in a code editor from your browser. This editor just got richer with the ability to use the component palette, property inspector, and structure pane while working on code directly. You can, for example, drag a component to your code, reposition it with the structure pane, and change its properties through the property inspector - all while working in "code" view. Also note the new right-click menu option that will show you the list of all the keyboard shortcuts you can use while editing code in Visual Builder. You'll notice updates to the other editors as well. For example the action chain editor has a new preview area, allowing you to easily navigate long action chains. It also no longer opens in a separate tab - keeping you in the context of the scope you are workin in. Another example is the business object diagram editor which now allows you to choose specific objects to show in the diagram. New Mobile Capabilities Visual Builder provide a great solution for building on-device mobile applications packaged either as native apps or distributed as Progressive Web Apps (PWA). New features allow you to access the device location, use the share functionality, and take videos with the camera in a declarative way with built in actions. New events allow you to handle your app being paused or resumed on the mobile device. We also improved the caching used by PWAs to speed up loading of apps. New Apps and Page Templates When you create mobile or web apps you'll notice new templates that offer various navigation approaches in mobile apps, and a new responsive + navigation template for web apps. In addition when creating mobile pages you'll be able to select from a wider choice of mobile optimized page layouts. As always you can further customize those templates and create your own layouts. Updated Infrastructure The new version of Visual Builder leverages Oracle JET version 7.1 out of the box. In addition new functionality allows you to specify specific JET versions for specific apps you create - giving you better control on their behavior. In addition new feature support coding with ES6 and ECMA2018 standards (while still able to degrade gracefully to support old browsers such as IE11). Visual Builder keeps expanding to new data centers across the world as the Oracle cloud expands - you can already find VB in Zurich, Tokyo, Seoul, and Mumbai in addition to existing centers in the US, Canada, and Europe. Much More There are many many other enhancements you'll find all over the tool, from new declarative ways to define search criteria in your queries, new UI components, improved CI/CD support, and better ways to manage app authorization and security.  Take Visual Builder for a spin and let us know what you thing on our community forum.      

We are happy to announce the roll out of the latest version of Oracle Visual Builder - version 19.3.1 - which contains many new features in every area of the service. In this blog entry we are going...

Consuming REST APIs in VB - multipart / form-data

In a previous post, we discussed integrating APIs with application/x-www-form-urlencoded payload.  In this post we will discuss integration of a POST API that has the multipart/form-data format.  Multipart/Form-Data is a popular format for REST APIs, since it can represent each key-value pair as a “part” with its own content type and disposition.  Each part is separated by a specific boundary string, and we don’t explicitly need Percent Encoding for their values.  Multipart/Form-Data payloads are especially popular in File Upload scenarios because the file can simply be represented by its own mime type. We will demonstrate multipart/form-data POST API integration with Visual Builder using the freely available https://postman-echo.com/post  API which accepts multipart/form-data format and returns the same input as a response.  A point to note is that multipart/form-data type requests are not testable in the Design time using the test tab (like we did for application/x-www-form-urlencoded payload).  However we can still configure the service connection and test it from within an application that calls this API. As before we divide the whole integration into 3 tasks: Defining the Service Connection  Creating a simple form with a file input and an input text element Passing the file input and the input text element to the Service Connection  Create the Service Connection The Postman Echo service is designed to accept arbitrary inputs, however we will pass the following individual parts : name : String myFile : a File Create the Service Connection using the "Define by Endpoint" flow Method = POST URL = https://postman-echo.com/post Action Hint = Create   In the Authentication tab, Enable Authentication/Proxy - checked Authentication = “None” (In a real world case, you will need to select appropriate authentication as per your service needs) Next in the Request tab, Media Type – change the default application/json to multipart/form-data using the pencil icon .  The Body part will be greyed out as in the previous example. In the Response tab, Supply an example response here like one below (it is not possible to Test the Service in this case).  The Media type for the response in our case continues to remain application/json; you can change it as per your service.  If you dont want to use the response in any way in your application, you can supply an empty json ( {} )as well. {     "args": {},     "data": {},     "files": {         "filename": "XXX"     },     "form": {         "name": "hello"     },     "json": null,     "url": "https://postman-echo.com/post" } Now click on “Create” to create the Service Connection This completes the definition of a Service Connection.  Let us now create a simple web application which will accept the a file and some other parameters and pass them to the Service as individual “parts” Create a form to gather data Create a web application.  Mine is called multiparttest Add an input text element by dragging it from the Component palette.  This will store the "name" attribute of our REST API payload Let us add a file picker in order to select a file from the local computer.  You will need to add the file picker component to the page imports, since this is not available in the standard components in the Component Palette.  More on the Orace JET filepicker component here. Next, toggle the VB page designer to the ‘Code’ mode.  Below the input text, add the following code which will add the filepicker: <div class="oj-flex">     <oj-file-picker id="oj-file-picker-1902456664-1" class="oj-sm-flex-1" accept="[[[ 'image/*']]]" selection-mode="single"></oj-file-picker> </div> Toggle back to ‘Design’ mode.  Create a page variable called ‘inputName’ of type String.  Bind this variable to the input Text element in our page.     Create an action chain for the FilePicker Next we add the Action chain which will run when we select the input file and pass the form data to the /post endpoint Select the filepicker and navigate to “Events”.  Select the Custom event option and choose “ojSelect” event, which occurs after we select the file from the picker.  On the "ojSelect" event, add a Page Action Chain called “FilePickerSelectChain” to handle this event.  The basic structure of the Action Chain is as follows: The elements of the Action chain are described below Call Rest Endpoint – Attach the Service Connection POST endpoint.  There are two things that need to be populated here (other things being optional) Content Type : multipart/form-data Body : (Static Content)  {  "myFile": "{{$chain.variables.detail.files[0]}}",  "name": "{{$page.variables.inputName}}" } Though the payload that is supplied looks like JSON, the VB runtime is designed to convert all the attributes in the JSON payload as individual parts of the multipart request with appropriate mime types.  So in our example both the attributes myFile and name would be the two parts of the multipart message   Success – Fire Notification Failure – Fire Notification   Now it’s time to run our application.  Remember we have configured our REST API to be triggered when a file is selected from the FilePicker.  You can trigger the API on click of a button as well. A quick inspection of Chrome Developer Tools reveals the Content type ( multipart/form-data) as well as the FormData elements      

In a previous post, we discussed integrating APIs with application/x-www-form-urlencoded payload.  In this post we will discuss integration of a POST API that has the multipart/form-data format. ...

Oracle Visual Builder Cloud Service

Consuming REST APIs in VB - application/x-www-form-urlencoded

Service Connections in Visual Builder support common payloads for REST APIs like application/json (default), application/x-www-form-urlencoded, multipart/form-data etc.  This series of blog posts will highlight how to integrate APIs with these payloads with Visual Builder. In this blog post, we will focus on the integration of a REST API that accepts application/x-www-form-urlencoded format.  This media type is less popular these days and is mostly replaced by multipart/form-data, which will be covered in a later post.  The form-urlencoded format can be visualized as a list of percent-encoded name-value pairs separated by the ampersand (&) character (much like the query string format).   For the purpose of demonstration of the various payloads I will be using the freely available REST client testing server https://postman-echo.com There are three broad tasks to create a full application that calls a REST API with application/x-www-form-urlencoded format  Defining the Service Connection  Creating a simple form with two input text elements bound to a page variable Passing the page variable to the Service Connection on click of a Button Each of these tasks are described below (If some of these are new to you, check out the Visual Builder learning path, especially the one on Service Connections) Define the Service Connection Create the Service Connection using “Define by Endpoint” flow.   Method = POST URL = https://postman-echo.com/post Action Hint = Create         Next, in the Authentication tab, give the following Enable Authentication/Proxy - checked Authentication = “None” (In a real world case, you will need to select appropriate authentication as per your service needs)     In the Request tab, change the default Media Type (application/json)  to application/x-www-form-urlencoded using the pencil icon .  As soon as you change this, the Body part will be greyed out (but we will still be able to test the Service)   Navigate to the Test tab.  Now, we will generate a sample Response by testing the Service  Request Body – lets have a string of simple key-value pairs as below(if you are using your own data, make sure these are Percent Encoded if they contain non-alphanumeric characters) firstValue=star&secondValue=wars  Click on the Send button.  You should be able to see the example response as below:       Click on the “Copy to Response Body” to store this as an example response, and finally click on “Create” to save the Service Connection Created This completes the definition of a Service Connection which is ready to be used in a Web or Mobile application. Create the form page Let us now create a simple web application which will accept the form parameters and pass them to the Service.  Create a web application with a logical name (mine is called “FormUrlEncodedTest”) From the main-start page, create a new Variable called “inputData” of type Object.  Add two fields to it “firstValue” and “secondValue”     On the main-start page, add two “Input text” components from the Component palette.  Change their labels to “First Value” and “Second Value” respectively. Click on the first input text, and in the Property inspector, click on Data sub tab.  Click on the "fx" icon to bind the and bind the input text data to "inputData.firstValue"   Repeat for the second input text field and bind it to secondValue attribute Finally add a button that will call the REST API and pass the values of both input elements.  Select the button and go to the Events tab and add a new Event.  Use the “ojAction” Quick Start to automatically create an Action chain for the event as well.     Add the Action Chain Next we add the Action chain elements.  In the Action chain, first we will prepare the body for the /post REST API using a custom JavaScript function and then call the /post  REST API and fire an appropriate notification if success or failure.     Create a page level function that takes care of Percent Encoding and forming the body of the request from the variable.  A sample function is as follows:     PageModule.prototype.prepareRestBody = function(details) {     var formBody = [];     for (var property in details) {       var encodedKey = encodeURIComponent(property);       var encodedValue = encodeURIComponent(details[property]);       formBody.push(encodedKey + "=" + encodedValue);     }     formBody = formBody.join("&");     return formBody;   }; In the Action chain, use the action “Call Module function” to use prepareRestBody, and we pass the variable we created ("inputData") to the input parameter "details"       Next, add the “Call Rest Endpoint action” to the action Chain and select the appropriate endpoint correspond to your API.  In our case it is the /post endpoint   We also need to map the body of the REST Action call with whatever was returned from the prepareRestbody module function Finally we add “Fire notification” actions to both the success and the failure nodes of the “Call Rest endpoint”.  For the success notification, we have a Notification type of “info” and we have also added the values retrieved from the response of the REST API to Summary as below: {{ $chain.results.callRestEndpoint1.body.form.firstValue + chain.results.callRestEndpoint1.body.form.secondValue}}         This completes our web application.  On adding input values and clicking on the button, you should now see a successful response like this:      

Service Connections in Visual Builder support common payloads for REST APIs like application/json (default), application/x-www-form-urlencoded, multipart/form-data etc.  This series of blog...

Importing and Updating Apps Between Visual Builder Instances

Visual Builder has built in lifecycle for applications that supports hosting the development, test, and production instances of an app on a single server. But many companies prefer to separate their dev instances from their production instances - this allows them to separate the users accessing each instance, separate the backends that they are accessing, and guarantee that there is no development load on the production server. If that is the approach taken, you'll need to promote the app from the development VB instance to the production VB instance, and also take care of subsequent changes to the app. The solution for this need is the use of a shared code repository - which is available for you for free in the Oracle Developer Cloud. If you haven't yet watched the video that explains how to setup Visual Builder to work with the Git repository in Developer Cloud - you should watch that video first. This is an essential thing to do if multiple developers are working on your project. It is also the thing that will enable you to promote code between environments. Once your app code is inside the Git repo - you can leverage Visual Builder's "Import from Git" option in any other instance of VB - this will create your initial version of the app on your new instance. When someone changes the code in the repository (for example by checking in the latest changes from the development instance), you can pick up those changes in your production VB instance by connecting your app back to that git repository (and the specific branch you want to use) and doing a Reset Head operation - this will overwrite your local app definition on the production instance with the latest updates from your dev instance.  Note that if you already have a published application which is live, you would first need to create a new version of this app, so you could make changes to the code. Then you reset the code from head, and then you re-stage and re-publish the app. Your changes will be reflected in the running app as soon as you do this. And don't worry - as part of the re-publish step we will ask you what to do with the existing data in your business objects - just choose the option to "Keep existing data in live" and your data will stay as is while the rest of the app gets updated. In the video below you can see the full process: Note that in the video the process is done manually, if you are adopting DevOps automation approach you should look into the ability to use the build jobs in Developer Cloud to automate the process of staging and publishing apps each time code changes in a specific branch. This blog entry can get you started on your way to DevOps Visual Builder.  

Visual Builder has built in lifecycle for applications that supports hosting the development, test, and production instances of an app on a single server. But many companies prefer to separate their...

User Interface

Charts in Oracle Visual Builder - Data Structure and Performance Tips

One of the key ways to make your application drive better user results is to use charts. Chart makes it easier for users to turn raw data into useful information. As they say "A picture is worth a thousands words". Oracle Visual Builder's quick starts makes it very simple to create basic charts leveraging the data visualization components of Oracle JET. But if you require more complex charts and if you want to improve the performance of your application, you might want to go beyond the quick-start. This blog covers two topics: Reducing network traffic - the "add data" quick-start creates separate variables for each chart, which results in separate DB queries and separate sets of data. If you are sharing population between charts - you can extend one of the queries and eliminate another. In addition, if you need to further manipulate the returned data to show a third type of chart - switch the ADP instead of SDP. This way a single fetch can be used by multiple charts even if the data structure is different. Creating the needed data structure - different charts require different structures of data, and your REST calls don't always return the needed structure. You can use simple JavaScript methods to massage the data a REST service provides into the format your chart requires. Here is what you'll learn in the video (time stamps will help you skip parts you already know): 0:00-1:15 Creating charts with the "add data" quick start 1:15-3:15 Merging two charts to work with a single REST call, and using calculation on multiple columns in a chart 3:15-4:15 Explaining the data structure for a chart with more than one series 4:15- 7:15 Switching from ServiceDataProvider (SDP) to an ArrayDataProvider (ADP) - so the data will be available for further manipulation 7:15-8:45 Defining a new type and a new ADP with the needed structure for the new type of chart 8:45-11:00 Use a JavaScript method to transform the data structure.  11:00-End Bind a dual series chart to an ADP  Resources  An example of the data structure for the second chart is in the Oracle JET cookbook. Here is the JavaScript used to create this structure from the data structure returned from the BO REST service. It creates two series entries for each record returned from the BO - one for salary and the other for the computed bonus. PageModule.prototype.transform = function(result) { var newID = 1; if (result && result.length > 0) { var items = []; for (var i = 0; i < result.length; i++) { items.push({ id: newID++, group: result[i].name, series: "Salary", value: result[i].salary }); items.push({ id: newID++, group: result[i].name, series: "Bonus", value: result[i].bonus * result[i].salary }); } return items; } };

One of the key ways to make your application drive better user results is to use charts. Chart makes it easier for users to turn raw data into useful information. As they say "A picture is worth...

Oracle Visual Builder Cloud Service

Complex Queries in Visual Builder

Often, you have to filter a data set based on multiple search criteria like in the above image. In this case, you want to only create filterCriterion items for fields that have a value. Any field with null/undefined/empty string you want to skip. To accomplish this, create an object to hold your filter criteria with each of the fields named exactly as the parameters you need to pass in. In our case it's SrNumber and StatusCdMeaning. For Business Objects and Fusion Apps REST endpoints, you can define this filterCriteria variable using a Type from Endpoint to make sure the field names match exactly. Then add a page function that looks like this: PageModule.prototype.getQueryCriteria = function(filterObject) { var filterProps = Object.keys(filterObject); var criteria = []; filterProps.forEach(key => { var value = filterObject[key]; if (value !== undefined && value !== null && value !== '') { criteria.push({ attribute: key, op: "$co", value: value }); } }); return { criteria: criteria }; }; Finally, hook up the filter button's ojAction chain to contain an Assign Variables action. In the Assign Variables, map the SDP's filterCriterion as follows. Make sure it's set to be an expression and not static text. $page.functions.getQueryCriteria($page.variables.filterCriteria) Note that we don't specify a top-level operand on the filterCriteria so it will automatically use $and for SrNumber and SrStatus.

Often, you have to filter a data set based on multiple search criteria like in the above image. In this case, you want to only create filterCriterion items for fields that have a value. Any field with...

Storing Image Files in Your Database from a Visual Builder App

The business objects in Oracle Visual Builder let you store textual data, but what if you need to store some binary data such as images? You'll need to find a separate location to store those. Oracle has various solutions for this including the storage cloud and the content and experience cloud, in this blog we'll show you how to do this using Oracle ATP Database (or any other Oracle DB). The concept is simple, you create a table with a Blob type column in your DB, in that column you are going to store the images. You now need to expose that table through a REST service - and call that REST service from your Visual Builder app to load the images. In your Visual Builder app you can have a business object where one of the fields will contain the URL that is used to fetch the image back. In the video demo below I show you how to build this solution. The Database Part - ATP+ORDS I'm using an ORDS based module that exposes the get and post methods on the table. Blain Carter pointed me to this tutorial that covers creating the table and the ORDS interfaces. A couple of tips as you work through the tutorial: You need to first complete the method for getting a specific image by ID, before you can test the POST method (which depends on that GET method for the return value). The PL/SQL code I used is: declare image_id integer; begin insert into gallery (title,content_type,image) values (:title,:content_type,:body) returning id into image_id; commit; :status := 201; :location := image_id; end; And the parameters are: Note that I also needed to whitelist my VB instance on the ORDS side - so I'll be allowed to access that end point. Now that you have the backend services, it's a simple matter of building the VB based UI. The Visual Builder Part In VB you'll define service connections to work with the ORDS endpoints. Note that you'll need to switch the MediaType of the endpoints to accept image/png instead of the regular application/json. Then we use the take picture action to allow us to pick an image either from the hard-drive when running as a web app, or from the device when running as a mobile app. We then pass the file to the REST endpoint which creates a record in the DB storing the image. The REST service returns a URL address for the image location as the text value we store in the VB business object. The value is returned as part of the header - so we use this expression to get it: $chain.results.callRestEndpoint1.headers.get('location') Check out the video below to see the development process in VB: 0:00-1:30 Review the Database and ORDS structure 1:30-3:30 Define REST service connections in Visual Builder 3:30-5:30 Create Business Object and basic UI for mobile app 5:30-7:40 Creating an action chain to take a picture and load to DB 7:30-8:45 Test run in emulator 8:45-end PWA enable the app and test on device

The business objects in Oracle Visual Builder let you store textual data, but what if you need to store some binary data such as images? You'll need to find a separate location to store those. Oracle...

Adding Offline Capabilities to an Oracle Visual Builder App

Visual Builder allows you to create applications that can continue to function even when your device is disconnected from the network. To do that Visual Builder leverages the Oracle JET offline persistence toolkit. This toolkit enables your application to cache data on the client and serves it back from the cache when you are issuing the same REST call but your device doesn't have access to the server. It also allows you to "execute" operations such as adding records while offline - storing those requests on the client again - and then automate replaying them back when you are connected. In the demo video below I show how to add some of these capabilities to your application. It's important to note that adding offline capabilities requires knowledge in JavaScript coding and an understanding of the offline toolkit. This is not a simple drag and drop operation - so approach carefully. Leverage the extensive logging that the offline persistence can do and monitor it's messages in the browser's dev tools console to see what is happening when. In the video you'll also see how to clear the cache on the client which is sometimes needed to see the real functionality. The Visual Builder developer guide has a section that explains the concepts of offline persistence, and provides a basic starting point code sample. In the video below, I start from that code sample, then I modify it to change the cache strategy and implement support for POST operations and synch data changes on demand. Here is a breakdown of things you'll see in the video (allowing you to skip to the section you need): 0:00-1:30 - Exposing Oracle Database Table (Oracle ATP) with REST Services using ORDS and SQLDeveloper 1:30-4:45 - Building a simple Read/Create Visual Builder App Accessing above ORDS services 4:45-8:00 - Adding caching based on the book's sample 8:00-10:30 - Switching to use cache data only when offline 10:30- End - Adding handling of POST(Create) operations As you can see the interaction with the offline persistence layer is managed in the application's JavaScript area. Below is the code used in my app, with the parts that I change from the doc sample explained below. define([ 'vbsw/helpers/serviceWorkerHelpers', /** * Add the following entries to include the toolkit classes that you'll use. More information about these * classes can be found in the toolkit's API doc. See the link to the API doc in the paragraph before * this sample file. * */ 'persist/persistenceManager', 'persist/defaultResponseProxy', 'persist/persistenceUtils', 'persist/fetchStrategies', /** * Add the following entry to enable console logging while you develop your app with the toolkit. */ 'persist/impl/logger' ], function(ServiceWorkerHelpers, PersistenceManager, DefaultResponseProxy, PersistenceUtils, FetchStrategies, Logger) { 'use strict'; function AppModule() {} function OfflineHandler() { /** * Enable console logging of the toolkit for development testing */ Logger.option('level', Logger.LEVEL_LOG); Logger.option('writer', console); var options = { /** * The following code snippets implements the toolkit's CacheFirstStrategy. This strategy * checks the application's cache for the requested data before it makes a request to cache * data. The code snippet also disables the background fetch of data. */ requestHandlerOverride: { handlePost: handlePost }, fetchStrategy: FetchStrategies.getCacheIfOfflineStrategy({ backgroundFetch: 'disabled' }) }; this._responseProxy = DefaultResponseProxy.getResponseProxy(options); } OfflineHandler.prototype.handleRequest = function(request, scope) { /** * (Optional). Write output from the OfflineHandler to your browser's console. Useful to help * you understand the code that follows. */ console.log('OfflineHandler.handleRequest() url = ' + request.url + ' cache = ' + request.cache + ' mode = ' + request.mode); /** * Cache requests where the URL matches the scope for which you want data cached. */ if (request.url.match( 'https://yourserver.oraclecloudapps.com/ords/shay' )) { return this._responseProxy.processRequest(request); } return PersistenceManager.browserFetch(request); }; OfflineHandler.prototype.beforeSyncRequestListener = function(event) { return Promise.resolve(); }; OfflineHandler.prototype.afterSyncRequestListener = function(event) { return Promise.resolve(); }; AppModule.prototype.createOfflineHandler = function() { /** Create the OfflineHandler that makes the toolkit cache data URLs */ return Promise.resolve(new OfflineHandler()); }; AppModule.prototype.isOnline = function() { return ServiceWorkerHelpers.isOnline(); }; AppModule.prototype.forceOffline = function(flag) { return ServiceWorkerHelpers.forceOffline(flag).then(function() { /** if online, perform a data sync */ if (!flag) { return ServiceWorkerHelpers.syncOfflineData(); } return Promise.resolve(); }).catch(function(error) { console.error(error); }); }; AppModule.prototype.dataSynch = function() { return ServiceWorkerHelpers.syncOfflineData(); }; // custom implementation to handle the POST request var handlePost = function(request) { if (ServiceWorkerHelpers.isOnline()) {} return PersistenceUtils.requestToJSON(request).then(function( requestData) { console.log('Inside PersistenceUtils'); console.log(requestData); requestData.status = 202; requestData.statusText = 'OK'; requestData.headers['content-type'] = 'application/json'; requestData.headers['x-oracle-jscpt-cache-expiration-date'] = ''; // if the request contains an ETag then we have to generate a new one var ifMatch = requestData.headers['if-match']; var ifNoneMatch = requestData.headers['if-none-match']; if (ifMatch || ifNoneMatch) { var randomInt = Math.floor(Math.random() * 1000000); requestData.headers['etag'] = (Date.now() + randomInt).toString(); requestData.headers['x-oracle-jscpt-etag-generated'] = requestData.headers['etag']; delete requestData.headers['if-match']; delete requestData.headers['if-none-match']; } return PersistenceUtils.responseFromJSON(requestData); }); }; return AppModule; });   To highlight the major changes in the code done in the video: Line 40 - changed the fetch strategy to fetch data from the cache only when offline - doc  Line 37-39 - define a new method that will be used to handle POST operations Lines 98-125 - the custom method that handles POST operations (line 11,19 contain the extra needed library reference) Lines 93-95 - AppModule function to force synchronization of offline changes Keep in mind that offline caching should be used with an understanding of the risks involved. For example, your cached data can get stale and not match the real situation in the server.So while caching can be a nice performance boost, you should probably use it for data that is not frequently changing. Also since data is cached on the client, other people could access it if they get access to the client. Don't cache sensitive data that you don't want falling into the wrong hands if you loose your device.  

Visual Builder allows you to create applications that can continue to function even when your device is disconnected from the network. To do that Visual Builder leverages the Oracle JET offline persist...

Visual Builder - Prompting for User Input in an Action Chain

From time to time you may find it necessary to prompt for user input during the course of a Visual Builder Action Chain execution.  For example, as shown here, you might want to confirm that the user really wants to navigate somewhere, or check to see if they want to really delete that row, that kind of thing. Of course you can use the Oracle JET dialog component to provide the user interface for this, but how do you incorporate that into the flow of an Action Chain?  Well there are two approaches: You break the logical action chain into multiple chains, the first opens the required dialog using the Call Component Method Action, and then the various buttons on the dialog kick off separate action chains of their own. You effectively do everything from a single action chain and simply wait for the user input before carrying out the logic.  The first approach works well, but because the before-user-input and post-user-input actions are split into separate chains it can be hard to manage the code, so let's look at the second approach.  As an example I've implemented a vbBeforeExit Action Chain to always prompt the user before they navigate, so no matter how navigation is triggered this will always pop up.  You can see here that the chain is very simple, we call a page module function (checkWithUser) which will display the dialog followed by an If action which branches on the user decision to either continue with the navigation operation or will cancel it.  So the question is - how does this wait for the user to make the selection? The answer is using a Promise. If a module function returns a Promise then action chain processing will wait until that Promise is resolved before continuing to the next step and we'll be taking advantage of that here.   So let's look at the implementation of the Page Module function being called:   PageModule.prototype.checkWithUser = function() {     var self = this;     var checkPromise = new Promise(function(resolve) {       // save away the reference to the promise resolvling function       self.userInputComplete = resolve;       // Show the dialog      document.getElementById('confirmDialog').open();     });     return checkPromise;   }; In this function a couple of things are happening. First of all you can see that a Promise is created and the reference to it's resolve function is stashed into the Page Module (via self.userInputComplete), we'll call this from another function later.  Next the dialog is opened.  I've manually created the dialog in the page source view (remembering to add the import for ojs/ojdialog to the page JSON (See: Adding New Oracle JET UI Component to Visual Builder Cloud Service). Here's the code for this simple example: <div>   <oj-dialog style="display:none" id="confirmDialog" dialog-title="Navigate to the Next Page" cancel-behavior="none">     <div slot="body">       <p>Are you sure you want to navigate?</p>     </div>     <div slot="footer">       <oj-button id="confirmYes" on-oj-action="[[$listeners.confirmYesOjAction]]">Yes</oj-button>       <oj-button id="confirmNo" on-oj-action="[[$listeners.confirmNoOjAction]]">No</oj-button>     </div>   </oj-dialog> </div> And each of the on-oj-action listeners just calls the same action chain with different parameters: "confirmYesOjAction": {     "chains": [         {             "chainId": "dialogResponseChain",             "parameters": {                 "detail": "{{ $event.detail }}",                 "response":"YES"             }         }     ] }, "confirmNoOjAction": {     "chains": [         {             "chainId": "dialogResponseChain",             "parameters": {                 "detail": "{{ $event.detail }}",                 "response":"NO"             }         }     ] }  The dialogResponseChain action chain that they both call is very simple, all it does is call another Page Module method: And here's the implementation of that function: PageModule.prototype.userResponse = function(response) { var self = this; // close the dialog var dialog = document.getElementById('confirmDialog'); if (dialog.isOpen()) { dialog.close(); } if (self.userInputComplete) { self.userInputComplete(response); delete self.userInputComplete; } }; So this function first of all closes the dialog and then calls the saved promise resolver function (self.userInputComplete) passing it the requested response which, in this case, will either be the string YES or NO depending on which button the user pressed. This response will then be taken as the response of the original Module Method call that we made in the first chain and as soon as the resolve function is called that chain will free up and this response used by the if statement that follows as the next action. And that's it.  Of course this is a very simple example.  You could pop up a dialog to make simple yes/no decisions like I have here, or you could even gather user input, you can pass that back to the main action chain using the resolve function in the same way that we passed the Yes/No value. 

From time to time you may find it necessary to prompt for user input during the course of a Visual Builder Action Chain execution.  For example, as shown here, you might want to confirm that the user...

Oracle Visual Builder Cloud Service

Adventures in Mutation - Adding Rows to a Table or ListView in Oracle Visual Builder

Recently there have been a lots of questions from the Visual Builder community relating to how to display both a collection based UI such as a Table or ListView  and a data entry form for that collection on the same screen.  Something like the simple To-Do list application shown here: How such a screen can be implemented, depends on the Data Provider being used by the table or ListView. If an ArrayDataProvider is used then the add action chain would usually have three steps: Call the rest endpoint (usually a POST) to add the new row at the back end  Call a page function that takes the new todo task and the array backing the ArrayDataProvider, pushes the new task to the array and returns the updated array as the result of the function Call an assign variable acton to copy this result back on top of the backing array.  This will have the side effect of updating the Array Data Provider and in turn the table will be refreshed. If the Data Provider for the table is a ServiceDataProvider though, we'll often see a pattern like this for the Add button action chain:   So here, there are just two steps: the first to call the relevant POST to update the backend with the new task data, the second is  a Refresh Data Provider Event Action.  You'll find that this works just fine, however, there is a catch relating to the possible performance cost this this approach and other side effects, so let's learn some more: Lesson 1 - Refresh does not actually "Re-Query" the Data Provider It's a common misconception that the refresh variation of the data provider event causes a provider to "re-query" its data by calling the associated endpoint on the REST service, this is not strictly true. All refresh is is an event associated with the Data Provider object but which as no direct effect on the DataProvider itself.  What actually happens is that components such as the <oj-table> that are bound to the Data Provider will be internally listening out for Data Provider refresh and mutation events. When they see a refresh event they will generally grab an iterator over the Data Provider data set to get all the data again (including any updates, inserts and deletes).  Now, because the Service Data Provider does not actually cache any data itself, it will need to go back to the service with a GET call to get the data from scratch. So it appears that the refresh event caused a re-GET of the data, but in reality this is just a side effect of the event. You might also run into secondary side effects such as the component resetting its scroll point or forgetting it's current selection - all because it's doing what you told it to do.  So, why is this interesting?  Well in the case of a table backed with a Service Data Provider we can see that the simple two step action chain used to add the new task is actually quite expensive. We have one roundtrip to POST the new to-do task to the  backend and then we throw all of the task data we already have away and get it again from the back end with a fresh GET request.  In some cases this can be desirable because you really want to have an up to date picture of the state of the dataset on the server, sometimes, however, there is really no need to refresh the data you already know about.  This is where the other mutation events come in.  In this article I'm concentrating on the add event only, but I'll cover update and remove events in a later article. Lesson 2 - The add event is Purely Local  Another misconception we see is that the add (or update or remove) Data Provider event somehow should update the back end service with changes.  This is not the case.  These events are just like the refresh event, the only effect they have is on components that are bound to the Data Provider in question. So really you can think of  a Data Provider add event as being a message to any component that is interested to tell them that there is a new row and the information that is in it.  These components can then react by internally adding the new row without having to go back to the server to get it.  This of course is much more efficient! Reworking the Example  So we have a minor change to make to the action chain, rather than selecting the refresh option on the radio buttons for the Data Provider event we choose Mutate and then it's all about the payload for the add event.  You can find the documentation for the event payload in the Oracle JET documentation for DataProviderAddOperationEventDetail. But I'll explain what the elements of the payload are here in context.  If you define a Mutation Data Provider event and then click assign and expand Add, this is what you will see: I'll start with the simplest of these, the data element.  This simply needs to be set to the record that you are "adding". In most cases (such as when using the built-in business objects layer) this will actually be contained within the information returned from the POST call you used to create the new row in the first place.  The data will be an array because you can add multiple rows in one go should you wish to. The twist to watch out for is, in the typical case, this data object should actually be an items array inside of the data element - this matches itemsPath defined for the Service Data Provider. If your Service Data Provider has a different value for itemsPath then you should use that.  In this case, I'm using a standard Visual Builder Business Object and my REST POST action was called callPOSTNewTask, and so the data element of the add payload is: {"items":[ $chain.results.callPOSTNewTask.body ]} Make sure that the Expression radio button is selected when entering this, not Static Content. Next we have to map the keys element. This again is an array containing the keys of the row(s) we are trying to add, in the same order as the contents of the data.items[] array if there is more than one. As before, we can get the correct key ID for the POSTed row from the return payload of the POST REST action: [ $chain.results.callPOSTNewTask.body.id ] Again, make sure that the Expression radio button is selected when entering this. Finally we need to tell the Table or ListView where to add the new row.  This can be specified in one of two ways - either using the indexes element to indicate an absolute position or, in the next version of Visual Builder, using the addBeforeKeys element to indicate an insertion position which is relative to a particular existing row. Again, both of these elements are arrays so that you can add multiple rows in one go.  In this case I just want to add  the new task to the bottom of the table and I can use the special value of -1 for the index to achieve this (using 0 would insert at the top): [ -1 ] This time its OK if Static Content is selected. If you switch to JSON code view for the Data Provider Event action it then looks like this: "dataProviderAddMutationEvent": { "module": "vb/action/builtin/fireDataProviderEventAction", "label": "Add Mutation Event", "parameters": { "target": "{{ $page.variables.tasksListSDP }}", "add": { "data": "{{ {\"items\":[ $chain.results.callPOSTNewTask.body]} }}", "keys": "{{ [\n $chain.results.callPOSTNewTask.body.id\n] }}", "indexes": [ -1 ] } } } And visually the action chain looks like this: One nice side effect that you'll see of using this add mutation event is that when it happens the Table or ListView will animate the addition of the new row, so as well as being more efficient, it also provides a better user experience.   

Recently there have been a lots of questions from the Visual Builder community relating to how to display both a collection based UI such as a Table or ListView  and a data entry form for that...

Oracle Visual Builder Cloud Service

Service Methods for Business Objects in Visual Builder

In a previous blog I showed you how to create an object function for a business object to allow you to expose specific functionality on a specific row. This blog is a little variation on this capability showing you how to create service methods in your data layer that are not related to a specific row.  This is based on a use case a customer had where they would get data for a record in a table, if the row already exists in the table they need to update it. If it doesn't exist they need to create a new row with the data. The REST API provided by the Visual Builder business objects supports this use case as long as you have the id of the record you want to update. This is done with the upsert option for a POST call - see the information about this combined insert/update operation here. But the data that the customer got didn't have the id of the record they would need to update. Instead they had the information about another field in the object. To resolve this we can create a function in the BO layer that will search the set of records for a specific value in a specific field, and then update that record if the value is found, or insert a record if it doesn't exist. The tricky part is that object functions work on a specific record in a BO (the id of that record is part of the path to that REST endpoint). In our case, we don't have a row to work on. Instead, we are going to create a dummy business object, with a single row in it. Then we'll create the function on this business object, always invoking it with the id of the row that is in there. This technique could be useful for any generic function you need in you BO layer that doesn't directly relate to a specific row. The function itself is written in Groovy, the programming language used by the Visual Builder business objects layer. In the video you'll see how we use various methods available on BOs in groovy (such as methods to query, add filter condition, and insert new records). You can learn more about these and other methods in our new Groovy for Visual Builder Reference Book. In the video below you'll see how to add such a function and how to call it from the VB user interface. Note that these functions are also callable from other tools through simple REST calls.   For those interested in the specific code used in the sample it is: def vo = newView('Department') vo.appendViewCriteria("department = '"+dname+"'") vo.executeQuery() if (!vo.hasNext()){   r = vo.createRow()   r.maxSalary=salary;   r.department=dname;   vo.insertRow(r) } while (vo.hasNext()) {   def r = vo.next();   r.maxSalary = salary; }   Line 1 gets us a pointer to our business object Line 2 adds a "where" clause to the query associated with our instance Line 3 execute the query with this where clause in the If section starting at line 4 we take the case where no records where found, create a new row, populate the data in the fields in that row, and then insert it into the business object. In the while loop we handle the case where a record (or more) were found, and update that row with the new value. One more tip - when you want to invoke the function from outside Visual Builder - remember to pass in the content-type of application/vnd.oracle.adf.action+json

In a previous blog I showed you how to create an object function for a business object to allow you to expose specific functionality on a specific row. This blog is a little variation on this...

Oracle Visual Builder Cloud Service

May the 4th be with you: 4 reasons to use Visual Builder for your next app and other bad star wars puns

    1) Use the source, Luke We had a saying back in my early days of developer support at Borland. If a challenging issue came in a senior engineer would tell us "Use the source, Luke" and we would dutifully follow the logic with a breakpoint debugger until the bug/issue revealed itself. Of course, most declarative tools like Visual Builder generate code but oftentimes these types of tools choose to hide the implementation from the app developer. All of the HTML 5, CSS, and Javascript (as well as required JSON metadata files) are provided for your editing and management.  However, the power of the declarative, drag and drop approach has not been compromised. In fact, Visual Builder contains even more visual tools than ever for not just UI layout and flow, but also creating custom logic, mapping variables and parameters, managing data and object relationships, and more.  An example action chain of complex, conditional logic from a button press action Having access to the source code is important, not just for troubleshooting and customization, but also for dev ops. Managing the code in a shared code repository makes the code easily versioned but also gives access for professional developers from whom you may need some custom code. You can also take advantage the advanced features of a dev ops environment, like Oracle Developer Cloud Service (a provided entitlement when you use the Oracle Platform), to manage builds and testing on check-in (push to Git)  for example.   2) I find your lack of REST disturbing REST has become the lingua franca of connectivity to services and Oracle PaaS and SaaS services have quickly adopted it. Visual Builder is all about REST and makes it easy to connect to other services whether they are well described or not. Well described services publish a format, such as Swagger, that describes the API and allows tools like Visual Builder to generate programmatic access to those connections. Visual Builder goes one step further and makes it super simple to select the right API to data bind to a visual control for the proper operation. Visual Builder also connect to the Oracle API catalog as well as your internal catalog to automate the visibility of Oracle services that are readily available to you. Figure 1: Easily add services into your application from a Catalog, Specification, or Endpoint mapping Once imported, binding a UI control to your service call is as simple as selecting the right endpoint for your intended operation. Those operations can be generally described as Create, Read, Update, Delete (CRUD) and the typical HTTP request type corresponds as such: Create = POST Read = GET Update = PATCH Delete = DELETE Shown below is the declarative approach within Visual Builder to bind a control to some service data.  1) Add data or create the page for the CRUD action 2) Select the endpoint for the CRUD action 3) Select the fields you want to retrieve or update Done. Both external service and local business objects present REST interfaces so there is a consistent approach to working with data.    3) These are not the devices you're looking for The line between mobile apps and web apps have become more blurred over these last few years. It used to be that in order to deliver a "native" mobile experience, you would have to build platform packages (IPA/APK) and deploy through the platform app store. With the "progress" in Progressive Web Apps (PWA), you can deliver apps to your devices without going through an App Store yet still providing a native experience. In this case, a native experience is defined as: Fullscreen app (no browser chrome like URL bar and back/forward buttons) Installed icon on device home screen to launch app Local assets "installed" to improve performance (no need to fetch pages/images initially) Platform specific look and feel Visual Builder now supports delivering your apps as PWA with the simple selection of the option in your app settings. Within your PWA steins you can add icon sets (Application Image Archive_ and specify which files you want cached when your PWA gets installed on the home screen.    4) Now, witness the firepower of this fully operational app platform Visual Builder delivers a modern and fresh approach to app development and its encouraging to see rapid application development (now called low-code) techniques being applied to web development with HTML and Javascript industry wide. Whether you are creating extensions to SaaS applications, modernizing existing on-premises systems, or building new web and mobile apps, we hope you'll give Visual Builder a go. And let us know what you think?

    1) Use the source, Luke We had a saying back in my early days of developer support at Borland. If a challenging issue came in a senior engineer would tell us "Use the source, Luke" and we would...

Oracle Visual Builder Cloud Service

Secure Static Headers for Visual Builder Service Connections

In Visual Builder 19.1.3 we introduced a new feature for Service connections – Secure Static Headers.  With this, we can now add header parameters to the Service connections which will only be applied securely from the VB server side and never be brought to the browser/client end. In a previous blog post , we discussed about the two broad strategies to connect to external Services from Visual Builder – Direct or Proxy.  In the Proxy method, we rely on the VB server side proxy to pass on our request to the external service with the appropriate authentication applied.  The credentials (client id/secret etc.) or the final Authorization header that is applied are never brought to the browser/client end.   What if there were other headers that we needed to pass to the service in this fashion?  For example – take the case of a service that has a special header called X-System-API-Key which needs to be transmitted securely.  In this case, the header can be added as a Secure Static Header. Another case could be systems where the Authorization header is given as a long lived Bearer token or a special key.  For example, Oracle Mobile Hub REST API has one such authentication option called the Anonymous key (shown in the below figure) which needs to be passed to the calling service as “Basic <AnonymousKey>” (See OMH documentation for more details).  We require two things to connect to an OMH backend REST API in this manner - the Anonymous key and the Backend ID. We can configure this in Visual Builder with Secure Static Headers.  You might have noted that Visual Builder gives you the flexibility of defining headers either at the Service level, or at individual Endpoint level.  If a particular header parameter is defined at Service level, it is applicable to all the Endpoints that are added to the Service (and saves you from the hassle of repeating this configuration for all endpoints).  The option of defining Secure Static Headers is only at the Service level for now. Below are the steps for connecting to an Oracle Mobile Hub Backend API with the Anonymous key using Visual Builder’s Secure Static headers functionality: Create a Service Connection by using “Define by Endpoint” flow.  For authentication, we are not given a username and password by Oracle Mobile Hub, but rather a string (“Basic <AnonymousKey>”), hence we would choose “Enable authentication/proxy” and choose “None” (and later add the Authorization as a secure static header).  Note we will not be able to add secure static headers just right now, because the options displayed in this flow are only to add headers at endpoint level Navigate to Response tab and provide an empty response body “{}” for now Create the Service Connection Open the newly created Service Connection, navigate to the Headers tab.  This now shows you a list of the Service level headers (which is empty in our case).  Add the following: Authorization header as a Secure Static header with the value “Basic <AnonymousKey>” obtained from OMH settings.   Oracle-mobile-backend-id as a Static header with the value of the <BackendId> obtained from the OMH settings. Now navigate to Endpoints, choose the required endpoint (/dummy in this example).  Navigate to the Test tab corresponding to this endpoint and test the service.  This should now give a successful result. Use the test response as an example by clicking on “Copy to Response Body”   Now this Service Connection is ready to be used in applications.  For adding another endpoint, simply go to the Service Connection -> Endpoints and add another Endpoint.  You will not need to add any Authorization / Oracle-Mobile-Backend-Id headers now, as they were already defined at the Service level.   Some additional points to note: The example of Oracle Mobile Hub using Anonymous key is only used as an illustration for Secure Static headers.  You can very well configure an Oracle Mobile Hub REST API with Basic Auth/Client Credentials/Resource Owner Password authentication as well “None” is the only authentication mechanism that allows you to define a static Authorization header.  If you try to use this with “Basic” for example, the hardcoded static Authorization header will be ignored, and whatever is set in the Authentication tab (Username / Password) will take precedence.    

In Visual Builder 19.1.3 we introduced a new feature for Service connections – Secure Static Headers.  With this, we can now add header parameters to the Service connections which will only be applied...

Oracle Visual Builder Cloud Service

Running Visual Builder Apps On Other Servers (and On-Premises)

Ever since we released Oracle Visual Builder a frequent request has been "can I take the app and run it anywhere I want?". With the latest version of Visual Builder the answer is Yes! This means that you can take apps you built in the Oracle Cloud and host it in other web servers. (Development is still cloud based only). Note that if you decide to take the visual builder server out of the picture, you are going to lose some of the functionality that runs on the Visual Builder Cloud Server, specifically: Business Objects - these run on the VB backend - so if you are not going to use our backend - you won't have a place to run them. (You could still run that part on the VB backend, and have your app UI served from another server). Identity Cloud - Visual Builder leverages Oracle's Identity Cloud to manage users and roles as well as authentication and authorization. If you are not using the VB Cloud hosting platform, it is up to you to manage these aspects of your app. Visual Builder proxy - On the Visual Builder server we have a piece of software (called the authentication proxy) that manages connections to REST services. The proxy handles things like passing in credentials and eliminating CORS (you can read more about the roles of the proxy and when to use it in this blog entry). If you don't want to use this piece of software you need to switch the connection of the services you define in VB to "Direct (bypass proxy)" and then the calls are being done directly from the browser to the remote REST service. If you are fine with these limitations, or if you have other solutions for these requirements, you can host your Oracle Visual Builder app on another web server without needing to access the VB server. (Remember that you can still choose to host your VB app somewhere else, but use the VB server for the above functionality - although if this is what you are doing, you are probably better off just hosting directly on VB). Here is a quick demo showing how to take an app and move it to run completely on your own machine (including accessing REST services and a database that is running on that machine). As you can see there are a couple of adjustments we did to our app to remove the dependency on the services that the Visual Builder server provides. We switch to use the direct access to the REST services, and we allowed anonymous access to our app (since we don't have IDCS to manage authentication). Then we used the grunt vb_build step (more on this in the blog entry about app optimization and CI/CD) to create the zip file that contains the app ready to be deployed - leveraging the archive artifact step in Developer cloud to save those files. We took the optimized version of the app and hosted it as a regular collection of HTML/JavaScript resources on a web server (Apache in the video). Then we showed how you can switch the set of services that the app is accessing by doing a "global search and replace" to replace the address of the server hosting the REST services that provides our app the data we use - this will allow you to also move your backend to be on-premise. (In the video we are using WebLogic to host ADF based REST services, accessing an Oracle XE database running in a docker image). With these simple steps you can easily host your VB applications anywhere.

Ever since we released Oracle Visual Builder a frequent request has been "can I take the app and run it anywhere I want?". With the latest version of Visual Builder the answer is Yes! This means that...

Oracle Visual Builder Cloud Service

Automating CI/CD and App Optimization for Visual Builder Apps with Developer Cloud

[Update Aug 2020 - there are new features in Visual Builder Studio and new Grunt tasks that further simplify this process - read the update on CI/CD for VB with VB Studio here.] The latest version of Visual Builder added support for app optimization as well as the ability to automate the staging and publishing of Visual Builder apps. To achieve this we use Grunt - a JavaScript task runner - and a set of grunt tasks specifically built for Visual Builder. A key thing that you can achieve with these commands is optimization of your delivered application - which can improve your runtime performance. We do this by minimizing the size of the resources that are downloaded to your clients. So this approach is recommended for use not just in cases where you want to automate delivery, but also in any application deployment process. The Visual Builder developer guide contains a section about the various grunt tasks you can use. While there are multiple tasks available, we'll focus on a couple of top level tasks that simplify the build process by executing a collection of other tasks in the correct order. The two main ones are vb-build and vb-publish. The vb-build command will take your application all the way to the staging stage (in the process executing the vb-clean, vb-process, vb-optimize, and vb-stage tasks). As you can see in the doc there are a bunch of parameters you can pass to the task the important ones are: id  the id of the app (see the VB app list home page) version the app's version (see the VB app list home page) username Your username password Your password - for better security choose a password type for this param in DevCS url the URL to your VB instance (including the ic/builder part) schema What to do with the DB schema - values can be dev/stage/live/new In the video below I'm defining a build job in DevCS and define these parameters with default values that match my app. Then I define a build step that uses a shell script that refers to those parameters like this: npm install   ./node_modules/.bin/grunt vb-build \   --url=${url} \   --username=${username} \   --password=${password} \   --id=${id} --ver=${ver} \   --schema=dev This command, for example, will take our source, optimize it, and stage it copying the data from the development database to the stage one. The second task, vb_publish, publishes the application - so it becomes accessible to the users. It has a similar set of parameter to the vb_build command. In the video I used: npm install   ./node_modules/.bin/grunt vb-publish \   --url=${serviceURL} \   --username=${username} \   --password=${password} \   --id=${id} --ver=${ver} \   --schema=new These tasks can be run on your own local machine, but a simpler way is to leverage Oracle Developer Cloud to automate the process. Leveraging DevCS lets you hook up this continuous delivery functionality directly to your Git code repository so you can, for example, automate staging a new version of the app after every code change. [small update - since the video was created the optimize parameter is no longer needed - we optimize your app in any case.] Note that you'll be using the build functionality of Developer Cloud, which means that your DevCS admin will need to define a build VM. Since we are using npm in our build steps, make sure that the build template used in your build job contains node.js as one of the software components. One other to watch out for is the version parameter in the build. Remember that you can't stage an app with the same version as a published app, so you would want to increase it the next time that you run a staging task after you ran a publish task.      

[Update Aug 2020 - there are new features in Visual Builder Studio and new Grunt tasks that further simplify this process - read the update on CI/CD for VB with VB Studio here.] The latest version of...

Oracle Visual Builder Cloud Service

Accessing DB objects through Oracle Integration Cloud for a Visual Builder App

[This is a guest post by Cosmin Manole from the Oracle Solution Hub Team] Visual Builder can quickly access data originating from Business Objects and external data sources that can be consumed through REST service endpoints. But what if a simple database connection is available with no REST endpoints exposed? In past blog entries we covered accessing the database with Java code (using ADF BC), and using PL/SQL based ORDS is another option, one additional possible solution is to leverage Oracle Integration Cloud, which allows CRUD operations to be implemented through Basic Routing integrations leveraging built-in database connections and queries. For this example we assume a connection to database is available and can be tested from OIC’s Integration service. The two main parts for this solution are: Exposing Data Through Integrations: This step creates REST endpoints for database actions In order for Integration Cloud to fulfill its role, a few actions are required: Create a database connection. This action is available from the Basic Routing configuration view, as well as from the Connections entry. In this example the connection is setup starting from the Integration configuration view. (part of the first video below) Create and configure the Basic Routing integrations required for each of the desired service actions (GET and PUT are showcased in the videos below (video 1 & 3) ) The available REST services will be consumed by VBCS (depicted in video 2 & video 3 for GET and PUT respectively) <video 1: create GET REST endpoint & required DBCS connection> The REST endpoint can now be used by VBCS. First, a Service Connection is created: <video 2: VBCS service connection – GET> The following video shows the creation of a new REST endpoint for updating a list item on the database. The action is registered with VBCS as a new service connection <video 3: create Integration update REST service & VBCS service connection PUT> Similarly, a POST action is added to the VBCS service connections. *Integration setup not part of the video for this scenario. <video 4: vbcs service connection POST> Consuming the REST services with Visual Builder Once the REST endpoints are available and tested they can be consumed by VBCS: Creating lists and managing information is easy through service connections and the underlying implementation is transparent to the UI developer. Developers can quickly display data and associate update, insert, or delete actions to buttons found in list items.  

[This is a guest post by Cosmin Manole from the Oracle Solution Hub Team] Visual Builder can quickly access data originating from Business Objects and external data sources that can be consumed...

Oracle Visual Builder Cloud Service

Oracle ERP Extension with Visual Builder Cloud Service

In this tutorial we're going to create a an extension to Oracle ERP that serves as a staging area for invoices and allows you to apply discounts to the line items on the invoice. Once the discount has been approved, there will be an action to create the invoice in ERP.  The app is based on Visual Builder Cloud Service business objects. Certain data, like customer and product info, is replicated from ERP into the VBCS business objects. In a real production setup, you would use Integration Cloud to schedule a data extract from ERP and into the VBCS on a regular basis. Here's what the data model looks like: Setting up the Project Import this file to your computer. In the VBCS home page, click Import > Import from File, and upload the ZIP there. Adding the List of Invoices Drag a table component into main-start. In the Quickstarts tab of the Property Inspector, click Add Data. Select Business Objects > Invoice and click Next. Select the following fields and click Next: BillToCustomerNumber BusinessUnit totalAmount discount discountedAmount Click Finish. Drag a Currency component onto the Discounted Amount column. The number changes from a regular number to a currency. Do the same for Total Amount. Drag a Percentage component onto the Discount column. Your finished table should look like this: Adding the Create Page By the end of this chapter, you will have: Added a Create page to your list of invoices Added an action chain on the Customer drop-down to populate the rest of the customer information Hard-coded the default value of fields like Transaction Type and others. Let's get started! Select the table in the Page Designer. Click the Quickstarts tab of the Property Inspector and click Add Create Page. Select Business Objects > Invoice and click Next. Select the following fields: customer (automatically added) BillToCustomer BusinessUnit InternalCurrencyCode PaymentTerms TransactionDate TransactionSource TransactionType status Change the Button Label to Create. Click Finish. Command-click the Create button to open the Create page in the Page Designer. Delete the Status field. Reorder the remaining fields so they look like this: Select the containing form-component and in the Property Inspector set Max Columns to 2. Set the following components to be read-only by selecting them and clicking Readonly in the Property Inspector: Bill To Customer Business Unit Internal Currency Code Payment Terms Transaction Source Transaction Type Select the Customer drop-down. In the Property Inspector, click the Events tab. Then click New Event > Quick Start: "value" Drag a Call REST Endpoint into the action chain. Click Select Endpoint and choose Business Objects > Customer > GET /Customer/{Customer_Id} In the Property Inspector, click Input Parameters > Customer_Id. Map value to Customer_Id. Drag an Assign Variables action to the success path below the Call REST Endpoint action. Click Assign in the right panel to open the mapper dialog. Map the fields from the response body of the REST call to your invoice page variable as shown below: businessUnit -> BusinessUnit customerNumber -> BillToCustomerNumber invoiceCurrencyCode -> InternalCurrencyCode Click Save and close the editor tab for the Action Chain. With main-create-invoice tab open in the Page Designer, click the Variables button in the sidebar. Expand {} invoice and set the default values for the following fields: TransactionSource -> Manual TransactionType -> Invoice status -> Requested PaymentTerms -> Net 15 Use the Run button to preview the app and to create a new record. Adding an Edit Page Our create page just fills in the general overview information of the invoice. Now we will create an edit page that allows us to enter line items, set the discount, and recalculate the total based on the discount and line items. Go back to main-start and select the table in the Page Designer. In the Quickstarts tab of the Property Inspector, click Add Edit Page. Select Invoice for the Read Endpoint and click Next. Then select Invoice for the Update Endpoint and click Next. On the final page of the wizard, select the following fields for inclusion: BillToCustomerNumber BusinessUnit InternalCurrencyCode PaymentTerms TransactionDate TransactionSource TransactionType customer discount discountedAmount totalAmount Rename the button label Edit. Click Finish. Open the Edit Page with Live Mode by selecting Live in the upper-right of the Page Designer, then selecting a row in the table and clicking the Edit Invoice button. This opens up the Edit page with the context of a row to edit. If no context is available, you'll get an error message in the Page Designer. Any time this happens, simply switch back to the main-start page, go into Live Mode, then open a record to edit. Don't forget to switch the Page Designer back to Design Mode once you've opened the Edit Page. Rearrange the fields so they look like this: Select the Form Layout (select anywhere around the fields in the Edit Page or open up the Structure View and click the Form Layout component there). In the Property Inspector, set Max Columns to 3 and Label Edge to top.  Set all of the fields except Customer, Transaction Date, and Discount to be read-only. Set up the Customer drop-down to populate the customer fields like you did in the Create page. (If you are short on time you can skip this part.) Select the Customer drop-down. In the Property Inspector, click the Events tab. Then click New Event > Quick Start: "value" Drag a Call REST Endpoint into the action chain. Click Select Endpoint and choose Business Objects > Customer > GET /Customer/{Customer_Id} In the Property Inspector, click Input Parameters > Customer_Id. Map value to Customer_Id. Drag an Assign Variables action to the success path below the Call REST Endpoint action. Map the fields from the response body of the REST call to your invoice page variable as shown below: businessUnit -> BusinessUnit customerNumber -> BillToCustomerNumber invoiceCurrencyCode -> InternalCurrencyCode Click Save and close the editor tab for the Action Chain. Select Total Amount and in the Property Inspector set the converter to $ and the Currency Code to USD. Your page should now look like this: Now let's update Discounted Amount so that it changes when we update the discount. Select Discounted Amount and in the Property Inspector click the Data tab. Set the value to: {{ $variables.invoice && $variables.invoice.discount !== undefined ? $variables.invoice.totalAmount * (1-$variables.invoice.discount) : $variables.invoice.totalAmount }} The basic information is now set up. However, if you run the page and try to save it, you'll get an error. This is because the app is trying to send all of the parameters that it fetched in the GET back to the PATCH endpoint, including two read-only fields (discountedAmount and totalAmount). These fields are read-only because we set them in the data model to be calculated from formulas/aggregations. We need to create a new payload variable that will store all of the read-write properties from the page and use that.  Click the Variables tab in the left sidebar of the Page Designer. Click the Types tab > + Type > From Endpoint. Select Invoice > PATCH /Invoice/{Invoice_Id}. Click Next. Name the type updatePayload and add the following fields from the Request node (not the Response node): BillToCustomerNumber BusinessUnit InternalCurrencyCode PaymentTerms TransactionDate TransactionSource TransactionType discount customer status Click Finish. Click the Actions tab in the left sidebar of the Page Designer. Click the SaveInvoiceChain action chain. Click the Variables tab in the left sidebar of the Action Chain Editor. Click + Variable and add a variable called payload of type updatePayload. Click the Action Chain tab in the left sidebar of the Action Chain Editor. Drag an Assign Variables action directly below the Start action. Click Variables -> Assign in the right sidebar of the Action Chain Designer. Map Page > Invoice to Action Chain > payload. Click Save.  Scroll down and select the Call REST Endpoint action. In the right sidebar, click Parameters > body. Delete the existing mapping and map Action Chain > payload to Parameters > body. Click Save. Adding the Line Item Child Table Now it's time for adding the UI to manage the line items for the invoices. Note that in the data model, each line item has a mandatory reference field to its parent invoice. Also, each line item has a lineTotal field which we will calculate based on the unit price, quantity, and discount. In this chapter you will: Add a table to the Edit Page and bind it to ReceivablesLineInvoice Set a filter on the table to only show line items for the current invoice Add a column with a line total calculated on the fly as the discount changes Add a Create page for the line item (in the interest of time we won't do an Edit page) Default the invoice reference in the newly created line item to point to the current invoice So let's get started! Open the Edit page in the Page Designer. Drag a Heading component between the Form Component and the Toolbar containing the Save and Cancel buttons. In the Property Inspector, set the Text to Line Items and the Level to H3. Drag a Table component below the Heading. In the Quickstarts tab of the Property Inspector, click Add Data. Select ReceivablesInvoiceLine in the wizard. (Hover over each node to see the full name of the business object.) Click Next. Add the following fields: Description Quantity UnitSellingPrice lineTotal Click Next. In the Define Query page, expand filterCriterion > criteria > item[0]. Select attribute and type invoice in the Expression field. Make sure it's set to Static Content and not Expression. Select op and type $eq in the Expression field.  Map Page > InvoiceId to the value field of the filterCriterion. Click Finish. Notice the Unit Selling Price and Line Total were entered as numbers and not currency. Drag a Currency component into each of the columns to change them to display as currencies.  Now let's add another column which will automatically update based on the discount amount. Drag a Text component to the slot at the end of the table. In the Property Inspector with the Text component selected, change the value to  {{ ($variables.invoice.discount !== undefined) ? (($current.row.Quantity * $current.row.UnitSellingPrice) * (1 - $variables.invoice.discount)) : ($current.row.Quantity * $current.row.UnitSellingPrice) }} Now let's fix the column header. In the Page Designer, select the table. In the Property Inspector, click Data and change the cellTemplate to Discounted Total. Now let's add the create page for the invoice. In the Page Designer, select the table and go to the Quickstarts tab of the Property Inspector. Click Add Create Page. Leave ReceivablesInvoiceLine selected as the endpoint and click Next. Add the following fields: Description LineNumber Quantity TaxClassificationCode UnitSellingPrice invoice lineTotal product Change the Button Label to Create. Click Finish. Open the Create page by switching to Live Mode and clicking the Create button that you just added. Delete the Description, Tax Classification Code, and Invoice fields, as we will default these. Rearrange the fields so your form looks like this: Make Unit Selling Price and Line Total read-only. Now let's update the fields in the page based on which product is selected, like we did with the Customer field on the main Invoice pages. Select the Product field, go to the Events tab of the Property Inspector, and click + New Event > Quick Start: value. Drag a Call REST Endpoint under the Start node. Click Select Endpoint in the right sidebar and choose Product > GET /Product/{Product_Id}. Click Select.  In the right sidebar, click Input Parameters > Product_Id. Map Action Chain > value to Parameters > Product_Id. Click Save. Drag an Assign Variables action into the success path. In the right sidebar, click Variables > Assign. Map description and unitSellingPrice from the REST response body to receivablesInvoiceLine > Description and receivablesInvoiceLine > UnitSellingPrice. Click Save and close the Action Chain editor tab. Back in the Line Item Create Page, select the Variables tab on the left and select receivablesInvoiceLine > TaxClassificationCode. Set the default value to FR VAT STD DEF RATE AP. Switch back to the Page Designer. Select Unit Selling Price, and in the Property Inspector, switch the Converter to $ and set the Currency Code to USD.  Do the same for Line Total. With Line Total still selected, click the Data tab of the Property Inspector and change the Value field to: {{ ($variables.receivablesInvoiceLine.Quantity && $variables.receivablesInvoiceLine.UnitSellingPrice) ? $variables.receivablesInvoiceLine.Quantity * $variables.receivablesInvoiceLine.UnitSellingPrice : 0 }} Now we need to change the Save action chain to calculate the lineTotal before sending the payload to the PUT endpoint. Select the Actions tab on the left and click createReceivablesInvoiceLineChain. Drag an Assign Variables action below the Start action. In the right sidebar, click Variables > Assign. Select Page > receivablesInvoiceLine > lineTotal and change the value to: $page.variables.receivablesInvoiceLine.Quantity * $page.variables.receivablesInvoiceLine.UnitSellingPrice Make sure that it's still set as an Expression and doesn't change to Static Content. Click Save. One last step! We need to pass in the Invoice Number when we navigate to the Create Line Item page and default the invoice reference to this value. Go back to the main-create-invoice-line page and click the Variables tab on the left. Click + Variable and add a String called InvoiceId. In the Property Inspector, make the string as a required input parameter that's passed on the URL. Go back to the main-edit-invoice page. Click the Actions tab in the left of the page and click navigateToCreateReceivablesInvoiceLineChain. Select the Navigate action and in the Property Inspector, click InvoiceId. Map Page > InvoiceId to Parameters > InvoiceId. Click Save. Go back to the main-create-receivables-invoice-line page and click the Variables tab on the left. Expand receivablesInvoiceLine and select invoice. Set the Default Value to {{$page.variables.InvoiceId}}. Adding a Custom Component Now let's add a custom Oracle JET Web Component to display a timeline of invoices.  Download this component to your computer. Open main-start in the editor. In the list of components, scroll down to the bottom and click the + sign in the Custom category. Drag the ZIP file into the dialog and click Import. The component gets added to the Palette. Update your SDP definition to include the fields that the custom component requires. Go to the Variables tab for main-start, click Types, and click Edit from Endpoint for getallInvoiceResponse. Select the status and TransactionDate fields (and leave all of the previously selected fields selected) and click Finish. Drag the component onto the page. In the Property Inspector for the my-timeline component, enter {{ $variables.invoiceListSDP }} for the items property. Building the ERP Integration So we've got our staging area for our invoices and for calculating our discounts all ready. Now we need to create an integration into ERP so we can create the invoices in ERP cloud. We will create a service connection to the POST receivablesInvoice REST API then use a custom JS function to prepare the payload. In the main application navigator, click Service Connections. Click + Service Connection. If your VB instance already has a registered SaaS API Catalog, then use the Select from Catalog functionality and skip to step 5 below. If not, select Define by Specification. Enter the following information: API Type: ADF Describe Service Specification: Web Address -  https://ERP_Base_URL/fscmRestApi/resources/11.13.18.05/receivablesInvoices/describe Service ID: invoices Authentication: Basic Username: CAROLINE.VALENCE (or some user that can call this service) Password: your password Click Next. Select receivablesInvoices > POST /receivablesInvoices and click Finish. Open main-edit-invoice and click the JS tab in the left sidebar. Enter the following code in bold in the JavaScript. var PageModule = function PageModule() {}; PageModule.prototype.getCreateInvoicePayload = function(invoice, invoiceLines) { var invoiceLineNumber = 1; return { BillToCustomerNumber : invoice.BillToCustomerNumber, BusinessUnit : invoice.BusinessUnit, InvoiceCurrencyCode : invoice.InternalCurrencyCode, PaymentTerms : invoice.PaymentTerms, TransactionDate : invoice.TransactionDate, TransactionSource : invoice.TransactionSource, TransactionType : invoice.TransactionType, receivablesInvoiceLines : invoiceLines.map(i => { return { Description : i.Description, LineNumber : invoiceLineNumber++, Quantity : i.Quantity, UnitSellingPrice : i.UnitSellingPrice * (1-invoice.discount), TaxClassificationCode : i.TaxClassificationCode }}) }; } return PageModule; Go back to the Page Designer tab and drag a new Button component next to the Save and Cancel buttons at the bottom of the page. Change the display text to Submit. Switch to the Events tab of the Property Inspector and click + New Event > Quick Start: 'ojAction' Drag a Call REST Endpoint action to the chain. Select Endpoint and select Business Objects > ReceivableInvoiceLine > GET /ReceivableInvoiceLine and click Select. With the Call REST Endpoint action selected, click Parameters > requestTransformOptions in the right sidebar. Expand Parameters > requestTransformOptions > filter > criteria > item. Set the following values: attribute: invoice (Static Content) operator: $eq (Static Content) value: $page.variables.invoiceId (Expression) Drag a Call Module Function action to the success path of the Call REST Endpoint. Click Select Module Function, select the getCreateInvoicePayload function, and click Select. Click Input Parameters > Assign and map Page > invoice to Parameters > invoice and Action Chain > Results > callRestEndpoint1 > body > items to Parameters > invoiceLines. Click Save. Drag a Call REST Endpoint action below the Call Module Function action. Click Select Endpoint and select the POST /receivablesInvoices endpoint. Click Parameters > body and map the output of the getCreateInvoicePayload function to the body. Click Save. Drag a Fire Notification action to the success path of the Call REST Endpoint action. Set the Summary to "Invoice created!", Notification Type to confirmation, and Display Mode to transient. Drag a Fire Notification action to the failure path of the Call REST Endpoint action. Set the summary to "Something went wrong!" and leave the rest of the fields at their defaults. Drag a Navigate action below the success Fire Notification action. Click Select target > Root Page > shell. This will navigate back home. Test out your app. You did it!  

In this tutorial we're going to create a an extension to Oracle ERP that serves as a staging area for invoices and allows you to apply discounts to the line items on the invoice. Once the discount has...

Say Cheese! Take Photo action improvements in Visual Builder 19.1.3 release

    Take Photo is a very useful action, especially on Mobile, as it provides access to the device camera. Take Photo is used to capture images, like personal photographs, as well as other uses, like scanning QR or bar codes. Depending on your use, you may need to just access the image on device or you may need to send it to another service, like a storage service.  Previous to the 19.1.3 release, Take Photo returned a file patch to the image on the local device. This path could easily be assigned directly to a JET image or avatar component in the next step of the action chain. However, if you needed to send it to a storage service, some preprocessing needed to be done on device to prepare it for delivery.  Vijaykumar Yenen has written an excellent article that details this previous behavior. It shows some of the custom code needed to prepare the image for upload to a service. Each storage service has different requirements for uploading images but generally you need to create a Base64 encoded string to send to the service. In some cases, the storage service has a POST operation that requires a pointer to the file. In those case, tools like Postman would provide a filepicker to select the file, and now in 19.1.3, Take Photo provides similar functionality by default. This behavior is seen in the new Media Type property in the Take Photo action, if set (by default) to "image."   However, what is you want the old behavior, i.e. assigning the file location to a JET image or avatar component. Well, there are a a couple of options. The easiest is to  remove "image" from the Media Type property and set it to nothing. In that case, the Take Photo action reverts to returning the file path. You can also write some custom code to convert the Blob stream to a URL which you can set to the src property of the image component. See the code sample below:   PageModule.prototype.showPic = function(fileBlob) {     const blobURL = URL.createObjectURL(fileBlob);     // Release the BLOB after it loads.     document.getElementById("mypic").onload = function() {       URL.revokeObjectURL(blobURL);     };     return blobURL;   }

    Take Photo is a very useful action, especially on Mobile, as it provides access to the device camera. Take Photo is used to capture images, like personal photographs, as well as other uses,...

Visual Builder Service Connections - Advanced topics

Service Connections are Visual Builder objects to represent REST API calls.  They are pretty much intuitive, and if you have used Postman or SOAP UI like tools to test web services, they will seem familiar, and yet there are some differences from these tools.  The aim of this blog post is to lay down some of the more advanced concepts around Service Connections.  For an introduction to Service Connections, refer to this blog If you have created a Visual Builder application that makes REST calls, you might have used a Service Connection by passing on an endpoint in a “Call Rest Endpoints action” in an action chain, or used them implicitly in a List or a Table that internally uses the same action.  When such an action is performed, there are two broad strategies to connect to REST APIs via Service Connections: Using the browser/client JavaScript to connect to the API Using the out-of-the-box VB Proxy to connect to the API Using the browser/client JavaScript to connect to the API In this, the request goes directly from the browser/mobile device to the External service as shown in the below figure:  It is similar to having Fetch API call from within your application’s client side JavaScript code as below: For simplicity we will call this browser JavaScript based method as “Direct” in the remainder of this post. Using the VB Proxy to connect to the API The VB Proxy is a server component of Visual Builder that can facilitate REST calls.  In this method, for every call, the request first goes to the Proxy, and then to the actual service being called.    What to choose : Direct or Proxy? Now, you may wonder which method to choose when calling a specific external service from Visual Builder.  There are some detriments to using the Proxy; namely it proxies each and every request, hence adding some extra latency. However there are cases, where Direct might not be the appropriate way to call your service as governed by the following three factors: Authentication method CORS support HTTPS support 1. Choice of Authentication method Some authentication methods are not suitable for directly calling the server from the browser, because the credentials used by these can be exposed in JavaScript.  For example. if you want to call an external service using Basic authentication, Direct wouldn’t be the right way at all, because the credentials to the service will be exposed to the client side JavaScript.  A quick look at the Network tab will also enable the users of your app get a hold of your external service credentials!       In general, Visual Builder doesn’t allow such combinations, thus protecting your application from any misconfiguration on part of the developer that could inadvertently leak credentials.  If you choose “Basic” in the authentication method of a Service Connection, the requests always go via the proxy (as shown below) and the Basic Auth credentials are applied at the proxy only, never being exposed to the client.  Authentication methods suitable for Direct For OAuth 2.0 based mechanisms (Client Credentials, Resource Owner Password, User Assertion OAuth) and for Oracle Cloud Account, you have an additional checkbox “Enable token relay” that specifies if the call is to made directly.    Unlike Basic Auth, these methods are safe to be called directly, because the credentials required for creating the token (username, password, client id, client secret) never travel to the client.  This is facilitated by another VB server side component called the Token Relay, which is in knowledge of these credentials, and creates the appropriate token, but only passes the final token to the client side and never the credentials that were used.  What if you have some custom JavaScript code that gets a bearer token through some process, and your requirement is only to pass the bearer token as-obtained to the Service Connection? In such cases of DIY authorization, you cannot use the VB Proxy as the it is designed strip off any Authorization header that is coming from the client, and re-insert the proxy configured Authorization headers.  To achieve this case, you can use “Direct” and give a dynamic “Authorization” header to the Service Connection endpoint as shown in the figure below.  Here an accessToken is obtained from some custom JavaScript code and then passed in via the dynamic header "Authorization" to the REST API.  Note that in this case the responsibility of maintaining the secrecy of the credentials procuring the token falls on you.     2. Available CORS support Further, there is another complication of Cross-Origin requests when calling services directly as opposed to via a proxy.  The browser is considered as an insecure environment, hence it blocks any external services that are being called with a domain that is different from the calling domain.  For example, if your app is running on domain vb.oraclecloud.com and your service is running on domain service.example.com, the browser first checks if the service.example.com domain has deemed JavaScript code served from vb.oraclecloud.com as allowed to call these services.  This is formally known as a CORS pre-flight request and consists of an OPTIONS call from the application to the service which returns several Access-Control-Allow-* headers.  From the value of these headers, the browser draws the conclusion whether or not the call to the external service is allowed (See wikipedia for a full description of CORS).  For such Cross-Origin requests to be allowed, you should have set the domain vb.oraclecloud.com in the CORS whitelist of service.example.com.  Note that this is a setting purely to be done on the remote server and not on Visual Builder.  If you have not set the Visual Builder domain (vb.oraclecloud.com for our example) in the CORS whitelist of the external service, you would get a pre-flight error in the browser console as follows “Access to fetch at 'https://service.example.com/service' from origin 'https://vb.oraclecloud.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource”.  The behavior of such a Service in the Test tab and the full CORS preflight error in the JavaScript console are shown below   Most modern resource servers support some sort of CORS configuration, or you could also set them programmatically.   However, in the case your external service doesn’t support CORS (or if you are unable to do this for some reason), you would need to call the service via a proxy. As an example, the Oracle Content and Experience Cloud have a facility in which an administrator can configure Allowed Origins.  In the example below, the Visual Builder domain is vb.oraclecloud.com, and that it is allowed to call REST APIs belonging to this Content and Experience Cloud Instance servers directly.  You should consult the documentation for the API being called to know it supports CORS.   This is one of the differences between calling a Service via Postman or SOAP UI and via VB Service connections.  You will never get a CORS pre-flight error from Postman, as you are not calling from one domain to another.  Mobile apps (native/hybrid) installed on a device are also exempt from CORS,   3. HTTPS Support Another requirement of direct calls is that they must be strictly HTTPS.  Though Visual Builder recommends HTTPS based Service connections only, for development purposes it is possible to use HTTP connections if their authentication mechanism that can be proxied.   Direct calls using HTTP will result in errors. If your external service has an HTTPS certificate that doesn’t have a fully valid CA (like a self-signed certificate), it will reject requests, results in errors.  This is a common scenario during development.   In case of direct connections, the browser will give out an error, and the resolution requires the browser to trust the certificate (import certificate into every browser where you test this app).  If the connection is via a proxy, you can import the certificate into Visual Builder.  An example scenario is shown here.   Configuring Direct/Proxy Configuring either of these two alternatives is not really a direct setting on the Service Connections, but actually a function of the selected authentication mechanism and some other bits, as shown below: * On the table below, “May have CORS issues” refers to the CORS-related scenarios explained above - i.e., when JavaScript code running on the browser makes a Rest call to a server that is not configured to allow such calls.   Service Connection Authentication settings Direct / Proxy Typical Scenario No defined authentication Direct No Authentication May have CORS issues Requires HTTPS None Proxy No Authentication Avoids CORS issues Allows HTTP Basic Proxy Basic Authentication Avoids CORS issues Allows HTTP Oracle Cloud Account, Token relay unchecked Proxy Authentication for calling services from the Service Catalog Avoids CORS issues Allows HTTP Oracle Cloud Account, Token relay checked Direct Authentication for calling services from the Service Catalog May have CORS issues Requires HTTPS Any OAuth 2.0 methods, Token relay unchecked Proxy OAuth 2.0 Authentication Avoids CORS issues Allows HTTP Any OAuth 2.0 methods, Token relay checked Direct OAuth 2.0 Authentication May have CORS issues Requires HTTPS Direct – Bypass proxy Direct No Authentication or authentication handled by the client code May have CORS issues Requires HTTPS Propagate Current User identity Direct Authentication for calling services from the from the pre-defined catalog, using the OAuth Implicit flow May have CORS issues Requires HTTPS

Service Connections are Visual Builder objects to represent REST API calls.  They are pretty much intuitive, and if you have used Postman or SOAP UI like tools to test web services, they will seem...

Oracle Visual Builder Cloud Service

Creating Progressive Web Apps with Oracle Visual Builder

Progressive Web Apps (or PWA for short) combine the advantages of on-device mobile app experience with the distribution simplicity offered by regular web applications. The latest version of Oracle Visual Builder offers a very easy way to create and distribute your PWAs in a visual cloud development environment. PWA apps can work offline, leverage device features such as access to the camera, photo gallery, and location information. The app is downloaded to the device, represented as an icon on the device list of apps, and when it is invoked you don't see a browser wrapper (no address bar and browser navigation buttons). As such the user experience of working with such application is very close to applications that you get from the app store. A key difference between PWA and on-device mobile apps is the distribution mechanism. To first "install" the application the user will navigate to a URL using their browser, this will pop-up an option for them to "add the application to home screen". Once they do this the app is now part of their "apps list" on the device. When a new version of the app is published, the end user doesn't need to go to the app store to download it. The application will automatically update on the device the next time you'll open it. Pulling the new UI from the server and caching it for future use. One more point to mention is that PWA can also install on your laptop, for example as a chrome app. This means that unlike the on-device mobile apps in VB that are limited to just iOS or Android devices, PWA apps are able to also run on windows, macs and other OSs. As you'll see in the demo video below, developing a PWA app is no different then developing regular mobile apps in Visual Builder, there is a configuration tab that allows you to turn on the PWA packaging for any mobile app. Once you do this, when you stage the app, you'll get a URL (and a QR code) that customers can access to invoke/install the app. Check out this demo A couple of notes about the app in the demo While we enabled unauthenticated access to the app, you can of course limit application access to specific users The data caching shown in the demo is the result of the REST service specifying a caching mechanism in the header. For more complete caching control and capabilities VB PWA apps can leverage the Oracle JET offline toolkit. The take a picture action also works when running on your laptop, it will open the local file selection dialog.      

Progressive Web Apps (or PWA for short) combine the advantages of on-device mobile app experience with the distribution simplicity offered by regular web applications. The latest version of...

Oracle Visual Builder Cloud Service

Conditional Formatting Row Values in a Table in Visual Builder

Color can help highlight important data in your application, calling out specific information you want the user to pay attention to. For example, if you have values that need special attention in a table of data, you might want to highlight them with a different color. Formatting an individual field is quite trivial, but when trying to do this for rows in a table you might need a bit of help. Here is the recipe: Assuming the decision of which format to show is a bit more complex than what can be represented as a simple EL, you'll want to use a pagemodule function that determine the format you want to show. Something like this:   PageModule.prototype.color = function(salary){     if (salary > 2000) {       return "red";     }     return "blue";   }    Then in your table, you'll want to have the specific field represented as a separate column template, which will then let you define the format for this field. To get this - drag and drop a Text component onto the existing field (see this "table tips" blog for a video about this approach). You'll then surround the field with a span component that you will format like this:         <template slot="Salary">         <span :style.color="{{$page.functions.color($current.data)}}">           <oj-bind-text value="[[$current.data]]">           </oj-bind-text>          </span>         </template> The result will be something like this:    

Color can help highlight important data in your application, calling out specific information you want the user to pay attention to. For example, if you have values that need special attention in a...

Oracle Visual Builder Cloud Service

Managing Visual Builder Development and Deployment Automation with Developer Cloud

The combination of Visual Builder and Oracle Developer Cloud Service (DevCS) gives your team a complete platform for managing and automating your application's development to deployment lifecycle. In the video below you can see an example development project and see how you can achieve a faster release cycle by leveraging this combination. Developer Cloud Service contains feature that include: Git version management repositories Issue tracking system with Agile dashboard to manage and track development sprint execution Merge request & peer code review system Build and deploy automation through pipelines Team collaboration tools such as an activity stream and wiki Note that Developer Cloud Service can be used to manage all your development artifacts, and is not limited to just Visual Builder apps. For example you can use the same platform to manage the REST services you create for accessing other sources of information regardless of the language they are built in. In a previous blog we showed you how to connect your Visual Builder instance to a new project in DevCS and push your code into the Git repository. Now we extend the scenario further showing the deeper integration you can have now. In the video below we look at a sample development flow of a Visual Builder team that include: Tracking issues in your application and assigning them to developers Managing code branches with Git Executing a code review process Automating build and deploy of applications Check out this powerful combination:

The combination of Visual Builder and Oracle Developer Cloud Service (DevCS) gives your team a complete platform for managing and automating your application's development to deployment lifecycle. In...

Oracle Visual Builder Cloud Service

New Features in Oracle Visual Builder - March 2019

The new version of Oracle Visual Builder released this month features several key features for developers looking to build mobile applications including support for Progressive Web Apps (PWA) development, pluggable Cordova Plug-ins, and improved device integration capabilities. This release also includes the initial release of our component exchange integration. Here is a quick rundown of the key new features released this month. PWA Packaging Progressive Web Apps (PWA) aim to merge the benefits of on-device mobile applications with the ease of distribution that web applications provide. When you create a PWA you get the benefits of on-device mobile apps such as:  native platform look and feel, icon for app invocation on the phone, device integration, and the ability to work offline. But the application doesn't need to be distributed through the app store, and when there is an update to the application, users don't need to download a new version. Instead, you provide a URL to the app and users who access the URL are given an option to add the app to their "homepage". When an update to the application is deployed, the new version will automatically download to the users phone the next time they access the app. Creating a PWA app in Visual Builder is easy, just pick up any mobile app that you created and switch the PWA enable switch on the setting tab, fill out some setup data and you are done. Now when you build your app we create the PWA packaging for you.   Custom Cordova Plug-in For on-device mobile applications Visual Builder uses a hybrid approach leveraging Apache Cordova to allow you to leverage device features. Visual Builder comes with built-in support for leveraging features such as the device's camera and location, but in some cases you might want to leverage other device capabilities.  The new pluggable Cordova plugin support will let you do just that. You can add Cordova plugins to your app and leverage them from our code. Find this under the application setting tab in the "Custom Plugins" section. (P.S. This updated functionality was actually in our February release). Take Photo Action Take photo is one of the built-in device interactions that Visual Builder offers. In the new version this action has been extended from just on-device mobile app support to work also in PWA apps as well as regular web apps. In mobile and PWA apps you'll have access to device camera and to photos in the device gallery. In web apps you'll be able to select images from your client hard-drive and upload them to the app. New Mobile App Template We added support for a new app template for your mobile apps. This one implements a collapsible left side navigation panel that allows you to navigate between flows easily without constantly occupying space on the screen. Application Optimization for Runtime A new feature in Visual Builder supports optimization of the application for runtime. Using a grunt based build job - that you can invoke as part of a Developer Cloud Service build pipeline, or on your own machine - you can optimize your application and publish it in one step. This enables you to further support a complete CI/CD flow with the combination of Visual Builder and DevCS. Oracle's Components Exchange With this release we are also releasing the first iteration of Oracle's Component Exchange - a place where we'll be publishing reusable components that you can easily add to your applications. These components are based on the Oracle JET Web Components architecture and can be further customized in your application. The exchange will also include new templates for applications. This is just the first step in our approach to helping you create and use reusable components in Visual Builder, expect more components to show up frequently, and future version are planned to also allow you to publish your own component exchange. That's Not All There are many other enhancements and additions to visual builder in this release. Read about them in the "What's New" document. Keep an eye on our blog for more detailed blog entries that will show you how to use each one of the new features. If you have any further questions, let us know on our community forum.

The new version of Oracle Visual Builder released this month features several key features for developers looking to build mobile applications including support for Progressive Web Apps (PWA)...

Oracle Visual Builder Cloud Service

Creating & Invoking Business Object Functions from Visual Builder UI

The business object layer in Visual Builder allows you to add business logic that can implement functionality on your data layer. In this blog we are going to show you how to use such a function to iterate over a set of records in a parent/child relationship, and update a set of records in a single REST call, as well as how to invoke that function from your visual builder UI. It's worth mentioning here that these functions can also be invoked from other applications that need access to your business services. Our example is a master/detail Departments/Employees scenario, where we want to build an interface that will let us update the salary of all the employees in a specific department with a bonus increase. While you can do this by calling a REST Patch operation on each employee independently, a more efficient way to do this would be to expose a single function that can update all the employees. Business Object Functions come to the rescue. We are going to define an object function that can be invoked on a specific department, accepts the bonus as a parameter, and then loops over all the employees working in this department and updates their salary with the new bonus. The groovy code for such a function is: def collection1 = Employees; while (collection1.hasNext()) {   def record1 = collection1.next();   record1.salary=record1.salary+bonus; } Note that the "Employees" in the first row is the name of the accessor that connects the two objects. In the video we show you how to define this accessor through the business object diagram in Visual Builder. We can mark this function to be "callable from external system" - which will then expose a REST endpoint on our business objects that will allow you to invoke the function from the Visual Builder pages (or other external systems). Now we are just left with the task of creating the UI to invoke this POST endpoint, passing in the needed parameters. Important note - if you want to invoke this function from outside VB you need to set the Content-Type header to application/vnd.oracle.adf.action+json . In the video below you can see how to: Create a master/detail UI - fetching employees for a specific department Add an accessor to a relationship between objects (to allow access to the employees from a specific department) Add an object function, provide parameters, and use code templates to loop over children Add an action chain that calls the REST POST endpoint passing in the parameters to the method

The business object layer in Visual Builder allows you to add business logic that can implement functionality on your data layer. In this blog we are going to show you how to use such a function...

Oracle Visual Builder Cloud Service

Navigating Between Pages and Flows

Flows are a feature in Visual Builder that can provide encapsulation that is smaller that the whole app but bigger than a page. A visual builder app has one or more root pages that define the shell and navigation for your app. These root pages load one or more flows in the main content area, and each flow has a default entry page that gets displayed when it is loaded. Flows do impose certain limitations on your app, and the most important one regards navigation. Currently the Visual Builder design time only allows you to navigate between pages inside a flow or back up to a root page. It does not allow you to navigate directly to a different flow, or to deep link to a page inside that flow. For example, if you have Customers in on flow, and Orders in another, and you want to link from a particular Order's page to the related Customer's page, you can't do it through the UI yet.  For this reason, we recommend that you put all of the related pages that need to link to each other inside a flow. Unfortunately, sometimes you can't. For example the Mobile Application template requires you to have one flow for each navigation button. The navigation pattern recommended in the Learning Path also assumes each nav link goes to a separate flow.  So let's take a look at how we can navigate from one flow to another using custom events: Download the sample for the Role-Based Security lesson, since it has the navigation bar already implemented. Import the app into VB and call it something like ExpenseReport_NavigateBetweenPages. Under the administration flow, create a new page called newpage. Add a paragraph tag to the page and change the text to "You made it!" Open main > main-start and add a hyperlink at the top of the page. Now we're ready to wire up the navigation. Open up root pages > shell. We're going to first create the action chain that does the navigation, then set up the custom event to fire the action chain. Go the Actions tab and create a new action chain called navigateToPage. Create two variables in the chain: a Boolean called navigate and a String called page. Mark them both as required. Drag an If action onto the chain and set the condition to $chain.variables.navigate. Drag a Navigate to Page action into the True path of the If condition.  Switch to the JSON view and enter the following for the  "navigateToPage1": { "module": "vb/action/builtin/navigateToPageAction", "parameters": { "history": "push", "page": "[[ $chain.variables.page ]]" } } Go to Events tab and open the Custom Events tab. Create a new custom event called customNavEvent. Add a parameter named event of type Any. Go to the Event Listeners tab and click + Event Listener. Search for customNavEvent and select it. Then select the navigateToPage action chain. Under Event Listeners, select customNavEvent -> navigateToPage. In the Property Inspector, click to assign parameters. Map navigate to true and the event to page. Now go back to main-start, select the hyperlink, and in the Events tab of the Property Inspector, use the quickstart to generate an action for the the click event. Drag a Fire Custom Event action onto the chain. Set the name to customNavEvent (it doesn't appear in the drop-down, you have to type it manually) and set the payload to administration/administration-newpage. Run the app and click the hyperlink. administration/administration-newpage opens. Passing a Parameter But what about if the page we're navigating to has a mandatory input parameter? How do I pass that in when navigating via the custom event. Never fear - payload is an object so we can pass in anything we like.  Go to administration/administration-newpage and create a new variable called name. Mark it as a required input parameter that gets passed in the URL. Change the text in your Paragraph to {{ "You made it, " + $page.variables.name }} Go back to the main-start/HyperlinkClickChain editor and click the {} Change the fireCustomEvent1 action to: "actions": { "fireCustomEvent1": { "module": "vb/action/builtin/fireCustomEventAction", "parameters": { "name": "customNavEvent", "payload": { "name": "john", "page": "administration/administration-newpage" } } } } Go to the shell page and open the Actions tab. Open the navigateToPage action chain. Click the variables tab and enter a new variable called name. Mark it as a required input parameter in the Property Inspector. Switch to the code view by clicking the {} button in the Action Chain Editor. Change the navigateToPage1 action to the following: "navigateToPage1": { "module": "vb/action/builtin/navigateToPageAction", "parameters": { "history": "push", "page": "[[ $variables.page ]]", "params": { "name": "{{ $variables.name }}" } } } Go back to the shell page and open the Events tab. Select customNavAction > navigateToPage and in the Property Inspector click the Assign link for the Input Parameters. Map name to $event.name and page to $event.page. Again, mark each as an Expression, not Static content. Run the app again. When you navigate to the page, it should say "You made it john".  

Flows are a feature in Visual Builder that can provide encapsulation that is smaller that the whole app but bigger than a page. A visual builder app has one or more root pages that define the shell...

Oracle Visual Builder Cloud Service

Debugging Visual Builder Mobile Apps on Android

Oracle Visual Builder lets you create mobile apps that install and run on your mobile device. In the development stages you can use our live emulator to see the apps running and test them. But how do you debug them once they are running on an actual mobile device? where can you find the log console to debug them? How do you get to the browser console when your app is running on a remote device? Here is the solution for Android apps (shown to me by Laura our VB Mobile PM): 1. First install the chrome ADB extension into your Chrome browser. The extension is available here. Once installed it will add a little green Android icon to your browser's menu. 2. Connect your Android device to your computer using a USB cable, and make sure that your phone is set to support USB debugging. On most devices this will be off by default, if you haven't configured your phone already you'll need to do this probably under the "Developer Options". Google and you'll find the specific steps based on your specific device. 3. In order to debug your application you'll need to configure a build profile that is set to Debug in the "Build Type" drop down. Then use that build profile to Run your application in the emulator, build it, and then deploy it to your mobile device. Once deployed with this profile you can run your app on your mobile device. 4. Now from the chrome browser click the little green Android icon, and choose View Inspection Target. You'll see a list of connected devices and running apps - including your Visual Builder mobile app. 5. Click the inspect link below it and you'll get a nice interface replicating the UI you see on the device and the browser's console. Need more tips on how to debug an app? I wrote a previous blog that covers techniques for debugging Visual Builder apps, and these techniques are still relevant for mobile apps. You'll see the same console and network tabs above for your on-device app.

Oracle Visual Builder lets you create mobile apps that install and run on your mobile device. In the development stages you can use our live emulator to see the apps running and test them. But how do...

Oracle Visual Builder Cloud Service

Introduction to Nested Flows in Oracle Visual Builder

One of the new features in the December release of Oracle Visual Builder Cloud Service is the new Nested Flows concept. Nested flows (also known as sub-flows) provide another level of encapsulation for your application. You define sub-flows inside another flow, and then you can include these flows in the pages that make up your master flow. Sub-flows are included inside your page leveraging a new flow container layout component. The idea is to allow you to break down specific functionality in your application into a unit that you can work on as an independent flow. This is quite useful in Single Page Applications, as it allows you to stay in the context of a page and still present context related information in a section of the page. It also allows a level of reusability since the same sub-flow can be included in multiple pages in the "master" flow. In the demo video below you can see the basics of creating nested flows, defining the page properties and containing area, designing the UI for the sub-flows, and adding navigation inside the sub-flows. Then we show how to add navigation from a containing page to dynamically decide which flow would be shown in the flow container area.

One of the new features in the December release of Oracle Visual Builder Cloud Service is the new Nested Flowsconcept. Nested flows (also known as sub-flows) provide another level of encapsulation for...

Oracle Visual Builder Cloud Service

Connecting VBCS to ORDS with self-signed certificates for Development

From Visual Builder 18.4.1 onwards, there is a facility for uploading trusted SSL certificates including self-signed certificates, which is normally needed during development. We have had a number of customers asking about how to use a self-signed certificate to connect to ORDS (Oracle Rest Data Services), which is a tool to create REST interfaces on top of relational data. ORDS exposes its REST APIs over an IP address, and when ORDS is installed, it simply creates a self-signed certificate for localhost.  This will not be trusted by Visual Builder when one tries to build a Service Connection to an ORDS API.  You might get an error like the one below:   If you have an ORDS URL like https://<IPAddress>/ords/pdb1/myworkspace/myhandler/my_ords_service, and are looking for a quick way to use the Service in VBCS with a self-signed certificate, here are steps that you might find handy.  However a bit of caution - these steps involve self-signed certificates in VB and only should be used in case of development not production!   Step 1 – Get the hostname for ORDS First find the ‘proper’ hostname for your ORDS IP address using the below: nslookup <ip address> This will give you the proper hostname to use for your service connections.  So instead of https://<IP address> use https://<hostname> Step 2 – Generate a self-signed certificate Create a self-signed certificate with openssl utility the above hostname as the CName and modify other attributes according to your need For e.g. openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -subj '/CN=<hostname>' This will yield two files key.pem and cert.pem Convert the key.pem to its der file as below: openssl pkcs8 -topk8 -inform PEM -outform DER -in key.pem -out key.der -nocrypt Similarly convert cert.pem to its crt file   openssl x509 -outform der -in cert.pem -out cert.crt Once you have these two, they need to be updated in the ORDS standalone.properties (More details can be found in the ORDS documentation) ssl.cert=/u01/app/oracle/product/ords/cert.crt ssl.cert.key=/u01/app/oracle/product/ords/key.der ssl.host=<hostname> Restart the ORDS server after making these changes. Step 3 – Upload the self-signed certificate to VB Go to Visual Builder -> Certificates (You require administrator privileges to do this).  Upload the cert.pem (or cert.crt) giving some alias.    Step 4 – Create the Service Connection Create the service connection in Visual Builder for the ORDS endpoint as you would create normally by using "Define by Endpoint" flow but remember to give the URL with the hostname instead of the IP address i.e. https://<hostname>/ords/pdb1/myworkspace/myhandler/my_ords_service.  (A detailed tutorial for creating and consuming  Service Connections is available here)   The Service Connection should now work.  Do remember that we have made Visual Builder trust all requests signed via this certificate, so it is imperative to keep this key secure, and as a best practice, never use self-signed certificates in production. EDIT : Corrected the command to convert to key.der          

From Visual Builder 18.4.1 onwards, there is a facility for uploading trusted SSL certificates including self-signed certificates, which is normally needed during development. We have had a number of...

Oracle Visual Builder Cloud Service

Editable Tables in Visual Builder - The Oracle JET 6 Way

[Update March 2020 - we have a new pattern recommended for creating editable tables - please refer to this approach instead of the one shown in this entry] A while back I blogged a solution to creating editable tables in Oracle Visual Builder, that was based on the approach that was used in the Oracle JET 5 cookbook - using a row template that you switch to show an editable version of each row. Now that Visual Builder 18.4.5 got released, we support using Oracle JET 6 in your application, and this provides a simpler way to create these type of editable tables with a column template. In the video below I show you how to leverage this approach, which also results in elimination of coding any JavaScript code. As you'll see you simply drag new UI components onto the column in the table that you want to edit. Then you make sure they point to the right values, and that they allow you to edit the value in them. Then when your table is in editMode you can simply edit the data using different types of input UI components. In the demo I also show how to add a save button that will save the data into your backend. As I mention in the video, the save approach I use is not the most efficient one. You would get better performance if you'll only save records you changed, and if you'll leverage the ability of the business objects in Visual Builder to execute multiple transactions in one go. In any case - this demo should get you started on your way to having editable tables: If you need more info on how to create the type and variables shown at the beginning of the video - check my previous blog entry on editable tables.    

[Update March 2020 - we have a new pattern recommended for creating editable tables - please refer to this approach instead of the one shown in this entry] A while back I blogged a solution to...

Oracle Visual Builder Cloud Service

New Features in Oracle Visual Builder December Release

We are happy to announce the December 2018 release of Oracle Visual Builder (known as 18.4.5). This version adds several key new features, and in addition implements many enhancements to the overall development experience in Oracle's high-productivity JavaScript development platform. Here are some of the new features you can now leverage: Integration Cloud Service Catalog If you are using Oracle Integration Cloud to connect and access data from various sources, Visual Builder now makes it even simpler to leverage those integrations. The new integrations service catalog will list integrations that are defined in your Oracle Integration Cloud, and allow you to add them as sources of data and operation easily to your VB application. This is a nice addition to the existing Oracle SaaS service catalog already available in Oracle VB. iPad/Tablet Support for Mobile Apps We extended our mobile packaging capabilities to support specific packaging for iPads in addition to iPhones. In addition, in the UI emulator VB now supports an iPad/Tablet size preview as another option in the screen sizes menu. Nested Flows To help you further encapsulate flows, Visual Builder now supports the concept of nested flows. Nested flows allow you to create sub-flows that are contained inside another flow and can be used by various pages in that "master" flow. These sub-flows are then embedded into a flow-container region on a page. At runtime you can switch the sub-flow that is shown in such a region giving you a more dynamic interface. This encapsulation also helps with scenarios of multiple developers that need to work on various sections of an application - eliminating potential conflicts. Visual Builder Add In for Excel Sometimes neither web nor mobile are the right UI for your customer, maybe they want to work with your data directly from spreadsheets - well now they can. With the Visual Builder Add in for Excel plug-in you can directly access Business Objects you created in Visual Builder from Excel spreadsheet and query and manipulate the data. The plug-in gives you a complete development environment embedded in Excel to create interactions with your business objects. JET 6 Support Visual Builder now supports the latest Oracle JET 6.0 set of components and capabilities. This applies for both design-time and run-time. Note that existing applications will continue to use their current JET version, unless you open them with the new version to do modifications - when you do open them, we'll automatically upgrade them to use JET 6. Vanity URL Visual Builder lets you define a specific URL that will be used for your published web applications. This means that if you own the URL to www.yourname.com for example - you can specify that your apps will show up using this URL. Check out the application settings for more information on this capability. But Wait There's More... There are many many other enhancements in every area of Oracle Visual Builder - you can read about them in our what's new book, or even better - just try out Visual Builder and experience it on your own!    

We are happy to announce the December 2018 release of Oracle Visual Builder (known as 18.4.5). This version adds several key new features, and in addition implements many enhancements to the overall...

Oracle Visual Builder Cloud Service

3 Tips for Using Imported Javascript with Visual Builder

In a previous article, I discussed how to import and use Javascript libraries. This has been a popular article and as such has generated a bunch of questions. In this article I am going to provide 3 tips that should address those questions and make it super easy to regularly import and use Javascript within your Visual Builder app.  1) Place your imported Javascript in the resources folder When you import your Javascript file, you select the folder for install at the time of import. In the previous article, I had imported the file into a flows folder and as such I had used a absolute path from the root of the instance to provide the location of the file. However, if you import into the resources folder you can now just reference your file by prepending "resources/" to the name of the JS file (you don't need the .js extension).   2) Use Code Insight to find the path the file Even better, you can use Code Insight to help you find the file. You invoke Code Insight with the Ctrl + Space bar. If you invoke Code Insight within the "" of the define in your custom code module you will see a Select URL... option pop up. Double click that menu option and you be presented with a empty text box to start typing the name of your file. Select the filename when it is found and hit Enter. The path will be added automatically for you and it will also remove the .js extension for you.   Don't forget to name your import in the function() of the require syntax. This is the name you will use to access your imported functions from that file. I named mine "importedjs" and as shown in the below code example I access my function using that scope - importedjs.callExternalAction define(["resources/importedjs"], function(importedjs) {   'use strict';   var PageModule = function PageModule() {};      PageModule.prototype.callImportedJSFunction = function(param)   {     return importedjs.callExternalAction(param);   }   return PageModule; }); 3) Export your custom code using AMD export syntax The last tip is the most important as I have received this question numerous times. If you are using 3rd party libraries, they likely already export their functions correctly. However if you are creating your own functions file, you need to export your functions using the AMD format. In this case AMD doesn't stand for Advanced Micro Devices but rather Asynchronous Module Definition (see Feature Image for this article). There is plenty of good material that describes the ins and outs of AMD format but I will use a simple example for this article with code shown below.  define([], function() { var exports = {}; function callExternalAction(param) {    return 'Processed value from external js: ' + param;  }; exports.callExternalAction = callExternalAction; return exports; }); The code above is setting up function(s) for export and assigning them to exported symbols. These are the names you will see when you use Code Insight on that filename as shown below. This is the basics of exporting in AMD format so if you follow this example you should be good to go.  You can download an example project at my GitHub. 

In a previous article, I discussed how to import and use Javascript libraries. This has been a popular article and as such has generated a bunch of questions. In this article I am going to provide 3...

Advanced Business Object Validation with Groovy

One of the powerful aspects of  Visual Builder's business objects is the ability to leverage Groovy code to implement complex logic for them. You can leverage Groovy in triggers, validators, and object functions - all residing under the "Business Rules" tab in Visual Builder design time. Groovy is quite a simple language, but when coding with the business objects in VB it is helpful to be aware of some unique methods that you can leverage to manipulate your business objects. We now have a book that provide a reference for Groovy usage in Visual Builder - check out the "Groovy Scripting Reference". One section that is specifically useful is the one titled "Accessing the View Object for Programmatic Access to Business Objects" as it shows you how to work with the data in a business object. Here is an example of how this can be useful. Example Suppose that we have a business object called Emp with two fields in it - name and salary. We want to verify that there are no records that have the exact same values for both name and salary. To do this we can add an object level validator (we called it checkUnique):   In this validator we add a piece of groovy code that will try and fetch existing records that have the same values as the current record we are working on (adding or modifying the record). The code needs to return true if the changes/addition are ok, and false if we want to fail the validation. The code used in our example is: def vo = newView('Emp'); vo.appendViewCriteria("name ='"+name+"' and salary = "+salary); vo.executeQuery(); def cnt = 0 while (vo.hasNext()) { vo.next() cnt = cnt + 1 } if (cnt > 1) { return false } else { return true } In line 1 we create a new instance of a view for the Emp object. In line 2 we add a criteria to the view, and in it we use the values from the current record for name and salary. Note that in the condition we use ' to surround character values. In line 3 we execute a query with this condition. In the rest of the code we are counting how many records are returned - and if it is more than 1 record we fail the validation. That's it - quite simple but powerful. P.S. If you are planning to do groovy coding, you'll want to quickly review the tips I provided in this blog entry on debugging the code using the log window in Visual Builder.    

One of the powerful aspects of  Visual Builder's business objects is the ability to leverage Groovy code to implement complex logic for them. You can leverage Groovy in triggers, validators, and...

Oracle Visual Builder Cloud Service

Managing Aggregation for Business Objects with Triggers

If you have data stored in business objects in Visual Builder you might want to present some information that requires aggregating data from multiple records. For example, if you have a list of employees and their salary, you might want to know the total number of employees and the total of the salaries. If you have a parent/child relationship you can do these type of calculations using the aggregated field functionality. For example if you have a departments table and each employee belongs to one department you can do the department level totals using aggregated fields. (You can see how to define this type of fields in this video around minute 3:45). Doing aggregations when there is no direct parent/child relationship is a bit trickier. Below I'm going to show you an approach to handling this using triggers on business objects that keep your totals always up to date. Note that one advantage of this approach is that the totals are not calculated on the fly each time you query them - rather they are kept already calculated in a dedicated business object. In the sample, I created a business object specifically for this tracking called "stats". This business objects has one record that contains the totals I need to track. I then use triggers to catch insert/update/delete operations on the employee object and update the stats object accordingly. As you'll see, we needed to resort to a bit of Groovy coding to achieve this type of updates to none related objects. You can get the base groovy code needed to update an object and a field in it by looking at the code that the visual "update record" operation creates. You can then modify this code to the exact logic you require. In the video you'll also see how you can access not just the current value of a field but also the old value of that field using the getOriginalAttributeValue(‘fieldName’)  groovy function. The code used in my update trigger is: def view1 = newView('Stats'); while (view1.hasNext()) { record1 = view1.next(); record1.totalSalary = { record1.totalSalary+salary-getOriginalAttributeValue('salary'); }.call(); } Note that in the video I didn't add the trigger for a delete event - but you can easily add this and simply have the following code in there: def view1 = newView('Stats'); while (view1.hasNext()) { record1 = view1.next(); record1.totalSalary = { record1.totalSalary-salary }.call(); record1.empCount = { record1.empCount-1 }.call(); }

If you have data stored in business objects in Visual Builder you might want to present some information that requires aggregating data from multiple records. For example, if you have a list of...

Oracle Visual Builder Cloud Service

Adding Off Canvas Layout to a Visual Builder Application

Off Canvas layout is a common UI pattern for modern applications, especially on mobile devices. The concept is aimed at saving space on your page, allowing you to pop out a "drawer" of additional information. This helps reduce clatter on the main page but still provide access to important data when needed without leaving the page context. You can see an example of the runtime behavior at the top of this post.  Oracle JET provides this type of "off-canvas" behavior as a built in component, and they have a demo of it working as part of the cookbook here. In the video below I show you how to add this to a Visual Builder application. As always - you can mostly just copy and paste code from the JET cookbook, but you need to handle some of the importing of resources a little different, and use the Visual Builder approach for adding your JavaScript function. The code used in the video is: Page source: <div class="oj-offcanvas-outer-wrapper">   <div class="oj-offcanvas-start oj-panel oj-panel-alt5 oj-offcanvas-overlay-shadow"     id="startDrawer" style="width: 200px">     <div class="oj-flex">       <h2 class="oj-flex-item oj-sm-12 oj-md-12" id="h1-1660298733-2">Menu</h2>     </div>     <div class="oj-flex">       <oj-label class="oj-flex-item oj-sm-12 oj-md-3" id="oj-label-1660298733-1">List</oj-label>     </div>     <div class="oj-flex">       <oj-label class="oj-flex-item oj-sm-12 oj-md-3" id="oj-label-1660298733-2">chart</oj-label>     </div>   </div>   <div class="demo-main-content" id="mainContent">     <div class="oj-flex">       <h2 class="oj-flex-item oj-sm-12 oj-md-10" id="h1-1660298733-1">Gifts</h2>     </div>     <div class="oj-flex">       <hr class="oj-flex-item oj-sm-12 oj-md-12" id="hr-1660298733-1" />     </div>     <div class="oj-flex">       <oj-list-view class="oj-flex-item oj-sm-12 oj-md-12" data="[[$page.variables.giftsListSDP]]"         id="oj-list-view-1660298733-1"> <template slot="itemTemplate"> <oj-vb-list-item> <img :src="[[$current.data.picture]]" height="32" slot="image" width="32" /> <p slot="title1"><oj-bind-text value="[[$current.data.product]]"></oj-bind-text></p> <p slot="value1"><oj-bind-text value="[[$current.data.cost]]"></oj-bind-text></p> <p slot="title2"><oj-bind-text value="[[$current.data.sKU]]"></oj-bind-text></p> </oj-vb-list-item> </template> </oj-list-view>     </div>   </div> </div> JavaScript Function in the page: define(['ojs/ojcore'], function(oj) { 'use strict'; var PageModule = function PageModule() {}; PageModule.prototype.showSide = function() { var offcanvas = { "selector": "#startDrawer", "content": "#mainContent", "edge": "start", "displayMode": "push", "size": "200px" }; oj.OffcanvasUtils.open(offcanvas); } return PageModule; }); and in your page Json file add this import: "oj-offCanvas": { "path": "ojs/ojoffcanvas" }

Off Canvas layout is a common UI pattern for modern applications, especially on mobile devices. The concept is aimed at saving space on your page, allowing you to pop out a "drawer" of additional...

Oracle Visual Builder Cloud Service

Debugging and Troubleshooting Visual Builder Logic

In every development cycle, developers are going to run into situations where things are not working as expected - this is where the debugging step comes into play. Oracle Visual Builder Cloud Service  uses a multi-tier architecture - so it is likely that you'll end up with the need to debug code in each one of the layers. In this short demo we give you some tips on how to debug your applications. At its core, VBCS is a web UI tool, so for most of the UI layer debugging you are going to rely on the development tools offered to your by your browser. In the video below I'm using the Chrome browser and its development tools - but similar tools exists in other browsers too. These tools allow you to see the network traffic between your client's browser and the REST sources of data. They also provide a console that shows you error messages and notifications sent from your application. One of the things we added to VBCS is a verbose mode of output that gives you full details on what's going on in your app at every step. Another layer that you might need to debug is the business object layer that exposes the REST services. If you are developing your business objects using VBCS, then you can use the built in logging mechanism for those. In the demonstration video below you'll see how to: Monitor REST calls Show notifications with variable values in the UI Track activity and variable values in the console Log messages in the console from custom JavaScript code - with console.log() Log messages from Groovy code in your business objects - with println() Track the log of your business object layer With these tools, understanding what is happening in your application should be quite easy - and fixing errors simpler. If you are still running into problems or questions with your development process - try posting on our VBCS community forum and some of your peers might be able to help.

In every development cycle, developers are going to run into situations where things are not working as expected - this is where the debugging step comes into play. Oracle Visual Builder Cloud Service...

Advanced Capabilities for the Table Components in Visual Builder - Tips

In this blog we'll show you how to turn-on some more advanced capabilities in table components you add to your web pages in Visual Builder Cloud Service. Specifically we'll cover, column content formatting, column resizing & reordering, line wrapping, scroll policies, and adding more columns. One thing that is worth mentioning first is that our UI gurus are not fans of tables. In general, they would recommend you'll use the list component to show collections of records. It's not just us, if you look at the UI of your facebook, twitter, instagram and even amazon product search results - all of those are not displayed as table - they show up as lists. So before you go down the table route - consider whether using lists will get you the functionality you need. If you picked up a table component, then after you used the initial quick start to bind data to it, there are a set of table and column attributes that you can use to add functionality to your table. See the following video to learn how to: Turn on Grid look and feel Reformat columns content to show in different ways (dates, pictures, gauges) Turn on column drag-and-drop reordering  Allow resizing columns Line-wrap long content in a column Control fetch size and data loading Add missing columns after you already ran the quick start Add row level actions  In the video I'm using the following values for the following attributes: Attribute Value column style white-space:normal column resizable enabled table scroll-policy-options {"fetchSize":3}   You can learn more about the table components in the JET cookbook section for the table component. And if you are interested in even more advanced capabilities you might want to check out this blog about creating editable tables in VBCS.

In this blog we'll show you how to turn-on some more advanced capabilities in table components you add to your web pages in Visual Builder Cloud Service. Specifically we'll cover, column content...

Oracle Visual Builder Cloud Service

Integrating Chatbots into VBCS Applications

Chatbots are integrated into VBCS using the Chatbot Web SDK. The hardest part is that you need to "configure" the SDK libraries to hardcode the URL of where the libraries will be deployed into the library JavaScript itself. This means you can't just add the libraries to the /resources directory of your application, since that URL changes depending on whether the application is in development, staging, or live mode. You also can't add it to another VB project, since its /resources directories are generated into randomly named directories when they are published. You therefore need to configure and stage your SDK to some other external location then point to it from the VBCS pro Note that there is no HTML component for the chatbot that you drag and drop from the component palette. You just add the JavaScript to the pages where you want the chatbot to appear and the libraries inject the elements into the DOM at runtime. Creating a Channel for the Bot We won't get into how to create a bot here. There are plenty of resources on that. Once it's created, you need to create a web channel for the bot. Open the chatbot in your Mobile Cloud/Digital Assistant UI Click the Settings tab on the left. Click Channels at the top and click New Channel Name the channel, set the type to Web Channel, and make it enabled. Copy the App Id property for the channel. Configuring and Staging the Chatbot Web SDK Download the OMCe Bots Client SDK for JavaScript from OTN and unzip it in a directory. Follow the instructions in the readme to configure and host it on a publicly available location. Embedding the Chatbot in Your Application Like we said, there is no HTML code or CCA to drop into a page. Instead you add the JavaScript to the PageModule and AppModule Javascript for your app. If you wanted the chatbot to only be available in one flow of your application, you would add the code to the FlowModule instead of the AppModule. Create an application called ChatbotClient and in that Web App called i.e. FlowerStore. (My chatbot allows you to order flowers; that's why I called it FlowerStore.) Open the application editor of FlowerStore by clicking the top-level FlowerStore node in the Web Apps tab. Open the JS tab of the editor and enter the following code in the the AppModule function - Make sure to replace XXX at the last line with your actual bot-sdk project URL: define([], function() { 'use strict'; var AppModule = function AppModule() { ! function(e, t, n, r) { function s() { try { var e; if ((e = "string" == typeof this.response ? JSON.parse(this.response) : this.response).url) { var n = t.getElementsByTagName("script")[0], r = t.createElement("script"); r.async = !0, r.src = e.url, n.parentNode.insertBefore(r, n) } } catch (e) {} } var o, p, a, i = [], c = []; e[n] = { init: function() { o = arguments; var e = { then: function(t) { return c.push({ type: "t", next: t }), e }, catch: function(t) { return c.push({ type: "c", next: t }), e } }; return e }, on: function() { i.push(arguments) }, render: function() { p = arguments }, destroy: function() { a = arguments } }, e.__onWebMessengerHostReady__ = function(t) { if (delete e.__onWebMessengerHostReady__, e[n] = t, o) for (var r = t.init.apply(t, o), s = 0; s < c.length; s++) { var u = c[s]; r = "t" === u.type ? r.then(u.next) : r.catch(u.next) } p && t.render.apply(t, p), a && t.destroy.apply(t, a); for (s = 0; s < i.length; s++) t.on.apply(t, i[s]) }; var u = new XMLHttpRequest; u.addEventListener("load", s), u.open("GET", r + "/loader.json", !0), u.responseType = "json", u.send() }(window, document, "Bots", "XXX"); }; return AppModule; }); Open the page editor for main-start. Open the JS tab of the editor and enter the following code in the PageModule function, replacing your-app-id with the App Id of your bot: define([], function() { 'use strict'; var PageModule = function PageModule() { Bots.init({ appId: 'your-app-id' }); }; return PageModule; }); Run your app and click the chatbot icon that appears on the page.  

Chatbots are integrated into VBCS using the Chatbot Web SDK. The hardest part is that you need to "configure" the SDK libraries to hardcode the URL of where the libraries will be deployed into...

Multi-Language Translations and Locale Switching in Visual Builder Applications

Oracle Visual Builder Cloud Service enables you to build applications that supports multiple languages - with an easy way to extract hard-coded strings in your app into a file that can be translated into other languages. This enables you to use the same running app to serve customers working in multiple languages. In the demo video below we'll show you some of the key features you'll be using to make your application multilingual. Replacing hard-coded strings with pointers to the translatable source Exporting and importing arb translation files Setting the default locale of your application in the app-flow.json file Dynamically switching locale at runtime (and storing the locale on the client for future use). One correction to the video - instead of passing the locale as just "en" you should pass a complete locale with the country too - so en-US or he-IL. In the video I'm using two pieces of code (that I got from Duncan Mills) : Adding the following to the app-flow.json file to define localization: "localization": { "locale": "{{ window.localStorage.getItem('vbcs.languageSwitcherApplication.locale') || 'en' }}" } A JavaScript method used to set the variable we keep on the machine to store default locale: PageModule.prototype.setAppLanguage = function(selectedLocale){ if (selectedLocale) { window.localStorage.setItem('vbcs.languageSwitcherApplication.locale',selectedLocale); } } By the way, VBCS (and Oracle JET) also supports right-to-left languages - so for example if you add translations to Hebrew and add a button that sets the locale variable to "he" you'll get Hebrew titles. But you'll need to do one more switch which is to modify the index.html file to have dir="rtl" add to the HTML tag. Then you can get the same app to looks like this:  

Oracle Visual Builder Cloud Service enables you to build applications that supports multiple languages - with an easy way to extract hard-coded strings in your app into a file that can be translated...

Defining Multiple REST End Points in Visual Builder - A Best Practice

Visual Builder Cloud Service makes it very easy to add REST services to your application - through the "new service connection" wizard you specify the URL to any REST service and a new entry is created for you. However, here is a small tip that will make your application management and performance better when you are leveraging multiple services from the same source - gather them into a single service. A service connection in VBCS can have multiple end-point defined in it. If you just run through the wizard for adding a service - each end point will create a new service definition. The best practice is to add new endpoint definition into the same service definition when possible.  Let's work through an example: We'll use a set of services about countries available here:  https://restcountries.eu/#api-endpoints-code You'll see for example these services there: https://restcountries.eu/rest/v2/name/{name}?fullText=true https://restcountries.eu/rest/v2/alpha/{code} The right way to add both to your project is: 1. Use the "Create Service" wizard to add the first end point: Going through the wizard will end up with a place for you to define the specific end point: And once you finish this section of the wizard your service will have one end point defined: Notice that in this page there is a big blue button "+Endpoint" - and you should click that one to add the next service/endpoint: Which will bring you into a similar flow for defining the second end point: That's it quite simple - now you have a single service definition with multiple end-points. One of the advantages of this approach is that if your source server changes an address - you just have one point to update, and this will take care of all the end points. Another advantage is runtime performances - VBCS doesn't need to upload and parse multiple service defintions - rather it does it only once, and leverages the information for all the end points.    

Visual Builder Cloud Service makes it very easy to add REST services to your application - through the "new service connection" wizard you specify the URL to any REST service and a new entry...

Creating Editable Tables in Oracle Visual Builder Cloud Service

[Note - since publishing this entry, Visual Builder upgraded to use JET 8 which has a new approach to creating editable tables see the new approach here.] A common request I've been getting from customers of Visual Builder is to be able to edit multiple records that are shown in a table. Oracle JET has an editable table sample that shows how to do this in their cookbook, but the translation from the JET approach to the VBCS way of doing things was a bit tricky for some. I recorded a video and included basic instructions showing you how to implement the JET sample in your VBCS application below.  Beyond just implementing the UI aspect of the editable table, you also need to define a strategy of when and how you want to save the data from the table back to the data source. In the video below I'm using an approach that is easy to implement, but is probably not the best way to implement this. I loop through all the records and update them back to the data source one-by-one. A better approach will be to keep a list of rows that were changed and only send them to be updated. Also - I'm using a button that saves the data all at once, you can alternatively use other events in the UI to save individual records - for example - maybe you'll want to save the data immediately when someone leaves a field. The point is that this demo is not a "Best practice" but rather an explanation of the basic mechanisms - you should adopt it to your use case. After this long intro, lets get into the details of what you need to do and what the video shows: Creating ArrayDataProvider variable (0:50) Populating the Array on page load with data (1:55) Basing a table on an ArrayDataProvider (3:15) How to add columns in a declarative way Adding row templates to the page - one for read and one for update row (4:04) Also shows how to manually add JET components to the page's definition Adding a function to decide which row template to show (5:55) Show how to add references to JQuery and Knockout to the function Show how to modify the function definition to be regular pagemodule function Adding a save operation (8:44) & Using a for loop in an action flow  I use the $current.index value to get to the right variable   As you can see - at the end of the day this is not too complex. It is also just scratching the surface of what you can do with the table - as the JET sample shows you can have different field types, validators and more. Some code from the sample I created: Page HTML source   Celebrities Save Page JavaScript define(['ojs/ojcore', 'knockout', 'jquery'], function(oj, ko, $) { 'use strict'; var PageModule = function PageModule() { var self = this; self._editRowRenderer = oj.KnockoutTemplateUtils.getRenderer( 'editRowTemplate', true); self._navRowRenderer = oj.KnockoutTemplateUtils.getRenderer( 'rowTemplate', true); PageModule.prototype.rowRenderer = function(context) { var mode = context['rowContext']['mode']; var renderer; if (mode === 'edit') { self._editRowRenderer(context); } else if (mode === 'navigation') { self._navRowRenderer(context); } }; }; return PageModule; });

[Note - since publishing this entry, Visual Builder upgraded to use JET 8 which has a new approach to creating editable tables see the new approach here.] A common request I've been getting from...

Oracle Visual Builder Cloud Service

Processes in VBCS Applications - Adding Task Buttons to a Business Object Edit Page

This blog is part of the series Visual Builder Cloud Service Learning Path. In a previous lesson, we designed the process we will use in our application. If you don't have it, you can download the process and the VBCS application and import them into your environments. We assume that you've named the process Expense Approvals and have already started the process in Test mode as described in the first chapter. In this chapter, we will add buttons to the bottom of the page for each of the task actions that are available to the current user for the current expense report record.  Getting the List of Tasks The first thing we will do is add an action to the loadExpenseReport action chain that fetches the list of tasks for processDefId that is stored with this Expense Report record. We will use a Type from Endpoint to create a type and variable that match the REST payload response for storing the information in the page's model. When designing this functionality, it's best to load a record in the Page Designer that has current tasks. To do this, create a new Expense Report (this will also launch an ExpenseApproval process), then edit this record in the Page Designer by switching to Live Mode and clicking it in either the list of Expense Reports or the Task List. With EditExpenseReport open in the Page Designer, click the Variables tab. Then click Types.  Click the button to add a new type from endpoint. Select Process Objects > tasks > GET tasks and click Next. Select the top-level Response to select the entire response. You can omit the []links if you like. Click Finish. Switch the Variables tab. Add a new variable called tasks of type getTaskCollection. Switch to the Actions panel and open loadExpenseReportChain. Drag a Get Task Collection action under Assign Variables expenseReportRecord. In the Property Inspector, click alias under Input Parameters.  Enter "ExpenseApproval" for the alias. Map Page > expenseReportRecord > processDefId on the left to processInstanceId on the right. Click Save. Drag an AssignVariables action below the Get Task Collection. In the Property Inspector, click Assign next to Variables. Map getTaskCollection1 > content on the left to Page > tasks on the right.  Close the action chain editor tab. Adding the Task Buttons To dynamically bind the buttons, we're going to do the following: Add an oj-bind-if that checks that the number of tasks is greater than zero. We're going to assume that the user will always only have one task assigned and so just hard-code the first result in the array of tasks that the REST service returns. Add a for-each loop to loop over all of the tasks. We will filter out system tasks Add a button in the template of the for-each loop for performing the task. Note that for the sake of simplicity we're leaving out some things we'd probably want to do, like save the record before executing the task. Switch back to the Page Designer for the EditExpenseReport page. Drop an If component in the toolbar next to the Save and Cancel buttons. In the Property Inspector, set Test to [[ $page.variables.tasks.items.length > 0]] Drop a For Each component inside the Bind-If component. Note it may be easier for you to select the right drop target by dragging and dropping into the Structure pane rather than into the Page Designer. In the Property Inspector, set Data to [[$page.variables.tasks.items[0].actions.filter(a => a.type === 'Custom')]] and As to task. Switch to the Source View and manually enter an oj-button in the template for the oj-bind-for-each element. (A bug prevents you from dropping the button using the Design view.) Switch back to the Design view. In the Page Structure view select the button so that you can see its properties in the Property Inspector. In the Property Inspector, set the Text to {{task.data.label}} Still with the Button selected, open the Events tab of the Property Inspector and click New Event -> Quick Start: 'click'. The tab with the new action chain opens. But before we can configure the action chain, we have to configure our input variables to hold the information we need. In the Action Chain editor, switch to the Variables view and create two string variables named actionId and taskId. Mark both as input variables in the Property Inspector Now let's pass in the info from the button as part of the click event. Open the EditExpenseReport page again, click the Events tab, and select the button click action that you generated with the quickstart. In the Property Inspector, click Assign for the Input Parameters. Map actionId to {{ $current.data.id }} and taskId to {{ $current.data.taskId }}. Click Save. Go back to the action chain editor for the ButtonClickAction1 and drop a Perform Task action onto the action chain. In the Property Inspector for the Perform Task action, click Assign for Parameters. Assign actionId on the left to id on the right. Assign taskId on the left to taskId on the right. Click Save. Drop a Navigate action under the Perform Task action. In the Property Inspector, click Select Target > Peer Page > main-start. Test the application by creating a new expense report, checking for the Approve task in the task list, then going to its Edit screen and performing the action with the buttons.  

This blog is part of the series Visual Builder Cloud Service Learning Path. In a previous lesson, we designed the process we will use in our application. If you don't have it, you can download the...

Oracle Visual Builder Cloud Service

Processes in VBCS Applications - Adding a Task List

This blog is part of the series Visual Builder Cloud Service Learning Path. In a previous lesson, we designed the process we will use in our application. If you don't have it, you can download the process and the VBCS application and import them into your environments. We assume that you've named the process Expense Approvals and have already started the process in Test mode as described in the first chapter. In this chapter, we will add a Task List that shows all of the currently active tasks for the logged in user. VBCS contains a quickstart to populate a table with a list of tasks for the current user and drop-down of available actions for each given task. The tricky part is hooking up the task list to the correctly list information from the business object, like the expense request name, and to link to the correct Edit page for the business object record. We do this by storing the information we pass into the PCS business object in the properties of the tasks. Configuring Tasks to Propagate Business Data We're going to highjack some of the standard properties of the tasks to pass business object informaiton.  (Note, in an upcoming release of PCS you'll be able to get fetch any PCS business object field with the list of tasks.) In PCS, open the ExpenseApproval process in the editor. Select the Approve Request task. Then click the menu icon and select Data Association. Map name and id from ExpenseApproval > Data Object > expenseReport on the left to title and longSummary from execData on the right. Then click Apply. Do the same for the Resubmit action. Save, publish, and test the process.  Adding the Task List to the Application We will add the task list by just dropping a table in the mytasks page and hooking it up to a ProcessDataProvider. Then we'll use the quickstart to add the Task Actions buttons. In VBCS, open the Web Apps tab and click the mytasks page to open it in the Editor. Drop a table component on the page.  In the Property Inspector for the table, choose the quickstarts tab and click Add Data. Choose Process Objects > task > GET tasks as the endpoint and click Next. Select the following columns:  label creationDate creationUser state Expand the query parameters and select the alias parameter. In the field at the bottom of the editor, type in "ExpenseApproval". Make sure to include the quotation marks. Click Finish. Preview the application and create a few records. Your task list table will look something like this: Select the table in the Page Designer and switch to the Data tab in the Property Inspector. Reorder and rename the columns so that they say: Expense Report Created By  Created On  Status Drag and drop an Input Date component onto the Created On column in the Page Designer. The display switches to correctly display as a date. Linking a Task to an Edit Page Now we'll link the values in the Expense Report column to the correct Edit page for the expense report record. In the Page Designer, drag and drop a Hyperlink component onto the Expense Report column in the table. The values turn into links. Click any of the column hyperlinks to select them in the Property Inspector. In the Events tab click New Event > Quick Start: 'click'. Before you can hook up the action chain, we have to pass in the ID of the expense report. Remember in PCS we mapped that into the longSummary field of the tasks. The REST call to the GET /tasks returns a payload with a field called description, which contains the longSummary field from the task. Go back to the my-tasks page and click the Events tab. In the Property Inspector, click key under Input Parameters. Select the key parameter in the right side of the dialog. In the field at the bottom of the type in $current.row.description. Click Save. Switch back to the HyperlinkClickAction tab. If you've closed it, you can find it in the Actions tab of the mytasks page. Drag a Navigate action onto the action chain. Click Select Target > Peer Page > EditExpenseReport. In the Property Inspector, click expenseReportId under Input Parameters. Map key to expenseReportId and click Save. Preview the mytasks page again. Click any of the links in the task list. The application navigates to the correct page. Adding a Task Actions Button Select the task list table in the Page Designer.  Open the Quick Starts panel of the Property Inspector and click Add Task Actions. Accept the default information and click OK. The Task Actions button is added above the list of tasks. Preview the page and select any task, then open the menu to choose from a list of actions to perform on the task. In the next section, we look at how to add Task buttons to the Edit page itself.

This blog is part of the series Visual Builder Cloud Service Learning Path. In a previous lesson, we designed the process we will use in our application. If you don't have it, you can download the...

Processes in VBCS Applications - Starting a Process from a VBCS Application

This blog is part of the series Visual Builder Cloud Service Learning Path. In the previous lesson, we designed the process we will use in our application. If you don't have it, you can download the process and the VBCS application and import them into your environments. We assume that you've named the process Expense Approvals and have already started the process in Test mode as described in the last chapter. In this tutorial, we'll look at how to start a process from our ExpenseReport VBCS application and pass in the required information as part of the REST call. This entails the following steps: Registering an Alias for the process in VBCS. This will allow us to reference the process without having to make changes to our code when we publish our application. Calling the Start Process REST API passing in the info that we marked as required on the Start message in the process. PCS needs to know the version and mode of the application so that it can correctly configure the REST URL to call back into VBCS business object REST endpoints. It also needs to have the name and id of the expense report item so we can correctly configure the Task List in VBCS. Storing the identifier of the the process we started back in the VBCS business object. This is so we can associate a specific expense report record with the correct instance of the approval process and show the right tasks for that record when we view its Edit screen. Registering the Process Alias In the Expense Report application in VBCS, click the Processes tab on the left. Then click the + sign at the top of the Processes tab. Select ExpenseApproval in the list, click Add, then click Close. If it doesn't appear, make sure Include test instances in selected and you have activated the process in Test mode in PCS as described in the last chapter. If it still doesn't show, try refreshing VBCS and opening the Register Deployed Process window again. Editing the CreateExpenseReport Action Chain to Start the Process Now we need to edit the create expense report action chain to do the following: Save the Expense Report record Save the record in a temporary action chain variable Call the Start Process REST endpoint, passing in the required attributes Store the processInstanceId from the response to the Start Process call into our temporary variable Call the PATCH REST endpoint for the Expense Report record we just created, passing in our temporary variable So let's do this now. In the Web Apps window, open expenses > flows > main > CreateExpenseReport.  Open the Actions tab, click the createExpenseReport action. Click the Variables tab in the left of the Action Chain Editor. Add a variable called patchPayload of type updateExpenseReportRequest. Click the Action Chain tab in the left of the Action Chain Editor to view the steps of the action chain again. Drag an Assign Variables action to the success path on the far left of the action chain. In the Property Inspector, click Assign next to Variables. Map Results > createExpenseReport > body to Action Chain > patchPayload. Click Save. Drag a Start Process action under the Assign Variables action you just added. In the Property Inspector, click Select Process.  Select Process Alias > ExpenseApproal > Receive Message In the Property Inspector, click startPayload under Input Parameters. Map id and name from Results > createExpenseReport > body on the left to id and name from Parameters > startPayload on the right. Click Save. Drag an Assign Variables action under the Start Process action that you just added. In the Property Inspector, click Assign next to Variables. Map Action Chain > Results > startProcess1 > content > id to Action Chain > patchPayload > processDefId on the right.  Drag a Call REST Endpoint action under the Assign Variables action that you just added. Click Select Endpoint. Select the PATCH /ExpenseReprort/{ExpenseReportId} endpoint. Under Input Parameters in the Property Inspector, click ExpenseReport_Id. Map Action Chain > Results > createExpenseReport > body > id on the left to Parameters > ExpenseReport_Id on the right. Click Save. Under Parameters in the Property Inspector, click body. Map Action Chain > patchPayload on the left to Parameters > body on the right. Click Save. Close the CreateExpenseReportChain tab. In the Page Designer for the CreateExpenseReport page, change the display text of the Save button to Submit. Test the application by entering a new expense report. In the PCS Test window, you will now see an instance in the Running Instances list. In the next chapter, we will add a Task List to the application.  

This blog is part of the series Visual Builder Cloud Service Learning Path. In the previous lesson, we designed the process we will use in our application. If you don't have it, you can download the...

Processes in VBCS Applications - Creating and Launching a Process

This blog is part of the series Visual Builder Cloud Service Learning Path. In this lesson we'll learn about how to back your VBCS application with an approval process in Process Cloud Service (PCS). PCS is included as part of Oracle Integration Cloud Enterprise, as is VBCS. In this tutorial, we'll look at how to create a process in PCS that can handle the approval process for your Expense Report application. Import this application to start the lesson. Creating the Process Here are a few key points about the process we are going to create: It is based on the Start With Message Approval template that is included in PCS. We will remove a few things to make it easier to work with. It contains a PCS Business Object called ExpenseReport that includes some key information that PCS needs to know in order to interact with the VBCS application We pass in this info by defining an ExpenseReport object as a parameter to the Start message and then mapping that data to the PCS ExpenseReport. The important thing to remember here is that the argument on the Start message only defines the shape of the data, while the Business Object in the process itself actually holds the data. Let's create our process. In the VBCS Expense Report application, open the Processes tab and click the menu button in the top right of the tab. Then click Design Processes. In the top-right corner of the Process Applications page, click Create > New Application. Name the application Expense Approvals and click Create. Click Start when a message is received. Then select Simple Message Approval Pattern, name the process ExpenseApproval, and click Create. Configuring the Process Let's remove a few things and do some basic setup.  Remove the Notify and Fulfill actions by selecting them then clicking the trash can icon above them. When you have exclusive gateways like the one after the Approve Request step, you set one path as being the default path and have to set a condition for all other paths. Let's set the condition for the No path. Select the No path then click the pencil icon. In the Property Inspector that opens at the bottom of the screen, click the pencil button next to the Condition field. Expand ExpenseApproval, select TaskOutcomeObject, and click the Insert Into Expression button.  Fill out the rest of the expression to say TaskOutcomeDataObject == "REJECT" Click OK. Creating the PCS Business Object Now let's create our ExpenseReport business object that will hold our data from the VBCS application In the left sidebar of the PCS window, click Business Types. In the top-right, click Create > New Business Object. Set ExpenseReport as the name and click Next. Insert the following fields, all strings, and click Finish. id​ name Note that id is an integer but because of some problems PCS has when dealing with integers we're just going to treat it as a string. Configuring the Start Message So above we created a business object shape. Now we have to: Use that shape to define the input parameter of the process Create an instance of the business object in the process Map the input parameter to the business object instance Let's do that now. Double-click the Receive Message node to open the property inspector. Click the pencil button next to Define Interface. Click the + button in the Arguments Definition list. Change the name to startPayload.  Click the down arrow next to string in the Type column. Expand Components and select BusinessData.ExpenseReport. Click OK. In the top-right of the Process window, click Data Objects. Click Add. In the dialog, set the name to expenseReport. Under Data Type, choose Business and select BusinessData.ExpenseReport. Click Create. Close the Data Objects dialog. Click the menu icon on the Start Message and choose Data Associations. Expand startPayload on the left and ExpenseApproval > Data Object > expenseReport on the right. Then map the id and name fields by dragging them onto the canvas in the middle. Click Apply. Running the Process in Test Mode Now let's save the project, publish our version, then run activate it in test mode. It's best to save and publish every time you make a change in the process and want to test it in VBCS. In the top-right of the Process window, click Save.  Click Publish at the top of the page. Add a comment in the Publish dialog and click Publish. Click Test in the top of the page. In the Test window, click the Activate button. Confirm the dialog that asks to add you to all roles.  Hopefully the validation window doesn't show any errors, but if so fix them in the process and save and publish again. The Running instances window will show you instances of the process that you launch from VBCS. We'll look at how to debug problems with the process in a later chapter. That's it! You're ready to hook this up to a VBCS Application, which we'll cover in the next chapter.

This blog is part of the series Visual Builder Cloud Service Learning Path. In this lesson we'll learn about how to back your VBCS application with an approval process in Process Cloud Service (PCS)....

Oracle Visual Builder Cloud Service

Integrating Processes into Visual Builder Cloud Applications

If you got Visual Builder Cloud Service as part of the Oracle Integration Cloud, then you have access to a powerful process creation and management service. Process Cloud helps you to create processes that can involve multiple steps ,multiple users and roles, and run over long periods. VBCS has specific functionality built-in to allow you to integrate these type of processes into your applications. Once you configure your process cloud service connection, you'll be able to add processes that you created in process cloud to your application. Then you can invoke and interact with them from both your user interface or the logic of your business objects. In the video below you get a quick introduction to several techniques used to interact with processes from VBCS. In the video you'll see: How to add a process to your app How to invoke it from action chains How to add processes and tasks to your UI How to leverage the process integration code templates created by VBCS How to invoke processes from business objects triggers  For more on working with processes and VBCS see the Working with Business Processes documentation chapter. We also added a set of blog entries that walk you through integrating PCS with VBCS in our Visual Builder Learning Path series of blogs. For a more complete introduction to process cloud service see the process cloud getting started page .  

If you got Visual Builder Cloud Service as part of the Oracle Integration Cloud, then you have access to a powerful process creation and management service. Process Cloud helps you to create processes...

Oracle Visual Builder Cloud Service

Visual Builder Mobile App Native Build Configuration Tips

A few tips to get mobile app build configuration right.   Mobile App Configuration Mobile app native build configuration is exposed as part of app settings Android build configuration 1. Keystore Generation Use keytool utility available with Java (JDK) is used to generate the keystore needed for signing your Android app. keytool is typically be available in your path, it provides a very quick way to generate a public/private key pair and store them in keystore. Here is link to detailed keytool documentation. Below is the screenshot of cmd line used to generate a keystore for my sample application for your reference: 2. Build Profile Configuration Configure the keystore values from the above as part of the Android build configuration as shown below. You can also select a specific profile as the default if you have more than one configuration. General recommendation is to have separate build profiles for development and production purposes.        iOS Configuration iOS configuration requires following guidelines from Apple to generate the provisioning profile and the certificate required for generating the IPA file. You would need a Apple Developer account to generate the above.  There are two flavors of Apple Developer accounts you could use for this purpose :  1. Standard Apple Developer Program : This is required for distributing your application via Apple AppStore.  2. Enterprise Developer Program : This allows companies to distribute apps to employees without going through the AppStore. If you are planning to build apps targeted for employees of your company this program is better suited than the standard developer program as you don't have to go through the Apple review to distribute your app. More details about the enterprise program are available here.  Generating .p12 file: A very nice step by step instructions video from Josh Morony here for creating p12 file on windows. If you are using a Mac you could create this a bit more easily following the instructions from Apple. Here is nice article I found useful for generating p12 file on Mac. Upload the p12 file to the Certificate field in the screen shot shown below. Enter the same password used while generating the p12 file in the Certificate password field. Provisioning Profile Variants: Development provisioning profile:  Typically used when running locally on a phone plugged in to your computer. This allows debugger access. A development provisioning profile allows apps signed by you to run on your registered devices.  In-House Distribution Provisioning Profile: If you want to develop and distribute apps privately within your company or to a selected number of end users, you can use a provisioning profile for in-house distribution. It's available only when using Apple Enterprise Program AppStore Provisioning Profile : This Distribution Provisioning Profile is available for the Apple Developer Program, allows you to generate a release version of your mobile app that can be published and distributed through the App Store. Ad Hoc: This allows you to generate a release version of your mobile app that can only be used in a limited list of devices. Use this profile to distribute your application to a limited group of end-users. Only the devices specified for the provisioning profile will be able install and launch the app. Often used when sending out to testers. Configuring Provisioning Profile: Upload the provisioning profile file in to the Provisioning Profile and in the Signing identity field enter the Common Name of the certificate. This is a bit tricky to get right and I have seen a lot of people getting this wrong. We are working on improving this but in the mean time follow these steps: 1. Install the certificate (p12 file) on your mac by double clicking it 2. It opens in the key chain app 3. Copy the Common Name as shown in the screenshot below        Build Configuration Screen                   

A few tips to get mobile app build configuration right.   Mobile App Configuration Mobile app native build configuration is exposed as part of app settings Android build configuration 1. Keystore...

Oracle Visual Builder Cloud Service

Tips and Tricks for List of Values in Visual Builder Cloud Service

While working on some customers' applications, I ran into a few performance and functionality tips related to list of values in Visual Builder Cloud Service (VBCS). While it is very tempting to use the built in quick start that binds a list to results from a service, in some cases you might want to take a different approach. One reason is performance - some lists don't change very often - and it makes more sense to fetch them only once instead of at every entry into a page. VBCS offers additional scopes for variables - and in the demo below I show how to use an application scope to only fetch a list of countries once (starting at 1:15). I also show how to define an array that will store the values of the list in a way that will allow you to access them from other locations in your app, and not just the specific UI component. The other scenario that the demo shows relates to situations where you need to get additional information on the record you selected in the list. For example, your list might have the code and label but might contain additional meaningful fields. What if you need access to those values for the selected record? In the demo below (6:40), I use a little JavaSciprt utility method that I add to the page to get the full details of the selected record from the list. The code used is (replace the two bold names with the id field and the value you want to return): PageModule.prototype.FindThreeLetter = function(list,value) {  return  list.find(record => record.alpha2_code === value).alpha3_code; } In the past, any array used for an LOV had to have "label" and "code" fields, but Oracle JET now allows you to set other fields to act in those roles this is shown at 5:54 using the options-keys property of the list component - a combobox in my case. Check it out:

While working on some customers' applications, I ran into a few performance and functionality tips related to list of values in Visual Builder Cloud Service (VBCS). While it is very tempting to use...

Oracle Visual Builder Cloud Service

Managing Visual Builder Code with Developer Cloud Service

Developer Cloud Service (DevCS for short) is a foundation service in the Oracle Cloud that provides you with a full cloud platform to manage agile development processes and automate DevOps cycles. It is available for every Oracle Cloud customer. One key capability (that is actually offered for free as part of your Oracle cloud subscription) is Git based repositories that you can create to manage the code of your application. In this blog we are going to show you how to leverage Visual Builder's built in integration with DevCS to manage your code lifecycle in these Git repositories. A full introduction to Git and the way you work with it - specifically the gitflow approach to code management is outside the scope of this blog. But since Git is the most popular version management solution out there - you can find many internet tutorials that will teach you how to implement these methodologies.  With the git integration in VBCS developing application in teams with multiple developers and multiple tasks is much more organized. In addition you have a full view of the code changes in your application and the ability to easily manage versions. In the video below we teach you some of the basic steps including: Creating a DevCS project with a default Git repository Connecting VBCS to DevCS and to a specific Git branch Pushing code into the repository Creating branches Pulling and importing code from repostiories Viewing code changes in DevCS The main concept to understand is that with this development approach, the app code source of truth becomes the git repository in DevCS. Developers then pull/import the code from that place to local copies in their DevCS development environment, where they can continue to develop it pushing changes back to the central repository. There is much more that you can do with DevCS and VBCS including managing and tracking issues, agile development processes and even automating the publishing of your applications. We'll cover these in upcoming blog entries. For more tips on using Developer Cloud Service see the DevCS documentation including the tutorials.  P.S. - note that if the user that you are using to access DevCS is federated from another place (such as in SSO situations) it won't be able to access the Git Repo. So instead create a new user in IDCS that will specifically be used for these tasks.

Developer Cloud Service (DevCS for short) is a foundation service in the Oracle Cloud that provides you with a full cloud platform to manage agile development processes and automate DevOps cycles. It...

Oracle Visual Builder Cloud Service

Importing and Using Javascript libraries in your Visual Builder custom code

In a recent post, I shared the prescriptive model for creating custom code within Visual Builder. Namely, using Javascript modules at the App, Flow, or Page level to create custom functions within the module. In this post, I want to talk about importing and using external Javascript libraries so you can use functions, objects and variables within that library. For this example, I will use the glmatrix library, a collection of Vectors, Matrices, and associated linear algebra operations. These types of operations can be used for more than just graphics so they live in their own library. The glmatrix library is provided in a "min" format. Essentially one free of whitespace and newline characters and in one file. So, the library I am importing is the glmatrixmin.js library which can be downloaded from the "dist" directory within the project github page: https://github.com/toji/gl-matrix/tree/master/dist. First, you'll need to import the library into your project. With Visual Builder, you can import resources at each of the levels, App, Flow, and Page and that resource will be accessible via that path. To import the file, right click on the project App, Flow, or Page node and select Import Resource. The resource needs to be uploaded as a zip file. So compress the glmatrixmin.js into a zip and select it from your files system in the Import Resources dialog. The dialog will show the import location. Remember this as this is how we reference the file later. Now the file is imported, you can see it in your code view under the Resources folder of the "main" Flow within which it was imported.  Now, we can write some custom code in our PageModule and reference the file to load it into our module. To do that we use a define statement, which provides the path to the file and the alias with which we will refer to the imported library in our code. See the below code example, for the define statement and usage. The full path to the file is used combining the import location with the flow name and resources directory. Note, the .js file extension is not necessary. Also, note the alias "glmatrix" is used to reference the objects and functions within the library.       

In a recent post, I shared the prescriptive model for creating custom code within Visual Builder. Namely, using Javascript modules at the App, Flow, or Page level to create custom functions...

Styling Visual Builder Cloud Service Applications

This blog is part of the series Visual Builder Cloud Service Learning Path. In this lesson we'll learn about how to style VBCS applications. All styling in VBCS applications happens manually in CSS. There are no declarative features for changing the display of text or images. As all VBCS applications are just JET applications, they use JET Themes to style the applications. When styling your VBCS or JET applications, it is important that you use theming correctly to do so, otherwise you run the risk of finding that your re-styling breaks when you upgrade your platform versions.  JET components provides a styling API through the use of SASS only, and any directly styled oj-* component selectors or other approaches will not be supported. This is because the internal structure of JET components, and the styles that they use, are subject to change from release to release. The published set of SASS variables constitutes a stable supported API that will internally re-map the configuration as required by internal changes within the JET implementation. Read the JET Dev Guide on Themes for more information. By default, all VBCS applications use the Alta UI Theme. VBCS applications have a built-in app.css file that you can use to define additional styling on top of the main Alta theme. For example, if you have made a <div> clickable, you may want to add a class called "clickable" to the div and define the CSS for the class so that it's highlighted, the cursor changes to a pointer when you hover over it, etc. If, however, you want to style the core elements of a VBCS theme, you should use SASS variables and generate the CSS rather than coding against the DOM elements directly using oj-* selectors in app.css. The reason is that the internal DOM of JET elements can and does change between releases of JET. Therefore a CSS that worked in one release may not work in another. SASS variables insulate you from these changes. Updating Your Project This lesson builds on the Expense Report project we have been using in the VBCS Learning Path. If you are starting at this lab, go to Building Your First VBCS Application and follow the steps to import the project, then continue below. Download this ZIP file to your computer. In your project, click the menu in the top right and choose Import Resources. Drag and drop the ZIP file into the dialog. Select Delete existing files and resources and click Import. Using Custom Classes in VBCS CSS Let's define a custom class to style clickable text in VBCS. As you can see when you open the main-start page, I've changed the list in the Expense Reports to have a clickable <h3> title for each expense report that navigates to the Edit page for that record. I've also added the custom class "clickable" to the div. In the Web Apps panel, open Expenses → resources → css → app.css and add the following code: .clickable { color: #07C; } .clickable:hover { cursor: hand; cursor: pointer; } Go back to your main-start page and reload the page in the Page Designer. Using a Custom Theme We won't go into how you actually create a new theme in JET. For that you can read the JET Dev Guide on Themes and try out the JET Theme Builder. The JET Theme Builder will generate a theme that looks like these: JET Stealth Theme JET Green Theme To use this theme in your application: In the Web Apps panel, expand Expenses → resources and right-click the css node. Choose Import. Drag and drop one of the above ZIPs and choose OK. For the Stealth them, for example, you should get a directory structure like this: Switch to the Source View panel and click index.html to open it in the code editor: Change the link to the CSS file to: <link type="text/css" rel="stylesheet" href="resources/css/stealth.css">

This blog is part of the series Visual Builder Cloud Service Learning Path. In this lesson we'll learn about how to style VBCS applications. All styling in VBCS applications happens manually in CSS....

Connecting to an External REST API (Twitter) in a Visual Builder Cloud Service Application

This blog is part of the series Visual Builder Cloud Service Learning Path. In this lesson, we will look at integrating a third party REST API that has no description document (Swagger or ADF Describe). We will integrate the Twitter API to fetch a list of tweets for a list celebrities stored in a custom Business Object. Importing the Starter Project We'll start the lesson with an application that already contains the Celebrities Business Object and mobile application with a list of celebrities and a details page for each one. Download this ZIP file to your computer. In the VBCS list of applications, click Import > Application from File. Drag and drop the ZIP file into the dialog and click Import. Creating an Application in Twitter Before you can connect to the Twitter APIs, you need to register for the developer program and create an app in Twitter. Go to https://developer.twitter.com/en/docs/basics/getting-started and follow the instructions under Get started: Build an app on Twitter. Registering the Twitter API In order to work with a REST API, VBCS needs to understand basic information about that REST service, such as: The service endpoints and verbs The required query parameters and headers The authentication method used to connect The transformation patterns for creating URLs for pagination, sorting, and filtering Since the Twitter API doesn't have Swagger documentation, we can run through a wizard to input this information manually. In the left sidebar, click the Service Connections icon Click the icon in the Services panel Click Define By Endpoint In the wizard, enter the following information and click Next: Field Value Method Get URL https://api.twitter.com/1.1/statuses/user_timeline.json Action Hint Get Many Service Base URL Leave default (https://api.twitter.com/1.1/statuses) In the Service tab, change the Service Name to Twitter. In the Authentication tab, enter the following information. Go to https://apps.twitter.com to get this information: Field Value Authentication Method Client Credentials OAuth 2.0 Client Id The Consumer Key (API Key) from your app Secret Consumer Secret (API Secret)  Scope Leave blank Authorization URL https://api.twitter.com/oauth2/token Enable token relay Leave unchecked Click Request > URL Parameters. Add the following Dynamic Query Parameter: screen_name – String Click Test. Enter SFGiants as the screen_name and click Send. The response body appears in the Body area below. Click the Copy to Response Body button. Click Create. Consuming the Twitter API Now let's drop a list into the Celebrity Detail page and populate it with a list of the celebrity's tweets. Go to the Mobile Apps panel and click Tweets > flows > main > CelebrityDetail. The page opens but gives a 404 error as there is no cebrityId provided.  Click the button and enter 1 in the dialog box. The page renders with the Katy Parry information.  Drop a List View under the Twitter Feed header.  In the Property Inspector, click Add Data. Under Twitter, select GET /user_timeline.json and click Next. Choose the first template and click Next. Add the created_at field to Field 2 and the and the text field to Field 4. Set the Primary Key to id. Click Next. Map celebrity > twitterHandle on the left to uriParameters > screen_name on the right. Click Finish. Wrapping the Twitter Feed List in an oj-bind-if If you run the app now you'll notice that the Twitter call isn't working. If you look at the REST call in the Chrome Developer Tools, you'll see it's passing undefined as the screen_name. That's because the page hasn't finished loading the celebrity details before it tries calling Twitter. We fix that by wrapping the list in an oj-bind-if and check that celebrity object is populated before we render the Twitter list. Right-click the list in ContactDetail and choose Surround With > If Right-click the list and choose Select Parent > If.  In the Property Inspector, change the test to: [[$page.variables.celebrityRecord.twitterHandle !== undefined]] Note: In our database we know that twitterHandle will always have a value. In more complex cases, you'll have to create more complex logic to handle null, undefined, empty string values, and other situations. Reload the page. The list of Tweets renders correctly.

This blog is part of the series Visual Builder Cloud Service Learning Path. In this lesson, we will look at integrating a third party REST API that has no description document (Swagger or ADF...

Oracle Visual Builder Cloud Service

Consuming Fusion Applications REST APIs in Visual Builder Cloud Service Applications

This blog is part of the series Visual Builder Cloud Service Learning Path. In this lesson we will look at consuming Fusion Applications REST services in a VBCS mobile application. In order to work with a REST API, VBCS needs to understand basic information about that REST service, such as: The service endpoints and verbs The required query parameters and headers The authentication method used to connect The transformation patterns for creating URLs for pagination, sorting, and filtering Fusion Applications like Oracle CX, HCM, and ERP clouds expose REST APIs that VBCS knows how to consume right out of the box.  There are three ways you hook up to register a REST connection: Select from Catalog - The Service Catalog shows all of the REST APIs for a registered Fusion instance. VBCS understands FA REST services out-of-the-box. See Authenticating Against FA below to see the requirements for Service Catalog Define by Specification - Enter the location of a Swagger or ADF-Describe document for a REST API. Use this to set up an App ID connection to any FA server, regardless of whether it meets the requirements in Authenticating Against FA. Define by Endpoint - Use this wizard to manually specify the required information about a REST endpoint. We will use this to register a Twitter API in a later lesson. Creating the Project and the Mobile Application In this lesson we will build the following UI over the FA Contacts REST endpoint: To do this we will access three endpoints: The GET ONE and GET MANY endpoints for /contacts The finder method that retrieves all of the country names, country codes, and other information Creating the Mobile App Create a new project called FAContactList In the Mobile Apps panel, click Create New Mobile App. Name the app Contacts and select None for the Navigation Style. Click Finish. Registering the Contacts REST API Click the Service Connections panel and click Add Service Connection. If you have a registered Service Catalog, click Select from Catalog.  If you do not have a registered Service Catalog, click Define by Specification. Switch the API Type to ADF Describe. Enter https://pathToYourCRM/crmRestApi/resources/latest/contacts/describe in the Service Specification field. Set the Service ID to contacts. Enable Basic Authentication and enter a set of valid credentials that has permission to call the REST API. Then click Next. Expand the /contacts node and select all of the following: GET /contacts GET /contacts/{contacts_Id} GET /fndTerritories;for=contacts-CountriesLOV Creating the List Select the main-start page in the Page Designer. Drop a List View onto the page. Select the List View in the Page Designer. (If you have just dropped it in, it will be selected already.) Then open the Property Inspector and select the Quickstarts page. Under crmRestApi, select contacts. Select the first template and click Next Add the following fields: Field 2: ContactName Field 3: AccountName Field 4: Country Click Next and then click Finish. Creating the Details Page Select the List View in the Page Designer. In the QuickStart tab of the Property Inspector, click Add Details Page. In the Select Endpoint page, select contacts and click Next. Add these fields: AccountName ContactName FormattedHomePhoneNumber FormattedMobileNumber PrimaryAddress > item[i] > FormattedAddress Click Finish. Open the ContactDetails page in the Page Designer Select the Form Layout and in the Property Inspector change the Label Edge variable to Top. All of the display labels move to above the input fields. Fix the display label text and reorder the fields so the page looks like this: Displaying LOV Labels in Collections and Details Pages As you can see, the list of Contacts is showing the country code instead of the full country name. This is because there is no one REST API that you can use to retrieve both the country codes and the display labels in the same call. Instead, we have to cache all of the country display labels in an application-scope variable when the application is first accessed. Then we will use a custom Javascript function to swap out the country codes for the display labels when the list is rendered. Adding the getLOVMeaningValue Function Open the application editor by opening the Mobile Apps panel and clicking the top-level Contacts node. Open the JavaScript panel of the application editor by clicking the JS button Add the getLOVMeaningValue function as shown in lines 6-22 below: define([], function() { 'use strict'; var AppModule = function AppModule() {}; AppModule.prototype.getLOVMeaningValue = function(key, lovs) { if (!lovs || !lovs[0]) { return; } var res; var keyProperty = Object.keys(lovs[0])[0]; lovs.forEach(function(record) { if (record[keyProperty] === key) { res = record; } }); if (res) { return res[Object.keys(res)[1]]; } }; return AppModule; }); Creating the Type and Variable for the Status Code Options Still in the application settings editor, open the Variables editor, then click the Types tab. Create a new Type from Endpoint based on the /fndTerritories;for=contacts-CountriesLOV endpoint. Change the name of the type to countryCodeOptions. Add TerritoryCode and TerritoryShortName to the Type and click Finish. Switch to the Variables tab. Create a new variable called countryCodes of type countryCodeOptions. Creating an Action to Populate Account Type Options Still in the application settings editor, open the Actions page. Create a new Action Chain called populateCountryCodes. Drag a Call REST Endpoint action from the left panel to underneath the Start node. In the Property Inspector, click Select Endpoint and select contacts > contacts  > /fndTerritories;for=contacts-CountriesLOV By default the REST call only returns the first 25 entries, but we want to cache all of the country names in our variable. So we will set a high limit for the REST call. In the property inspector, click limit under Input Parameters. Map the variable to 500, leaving it set as Static Content, and click OK. Add an Assign Variables action that maps the body returned by the Call REST action to the statusCodes flow variable. Return to the application editor and open the Events panel Create a new event: Event: vbEnter Action Chain: populateStatusCode Updating the List to Call the getLOVMeaningValue Function Open the Page Designer for main-start. Select any row in the list In the General tab of the Property Inspector, change the Value1 to: [[ $application.functions.getLOVMeaningValue($current.data.Country,$application.variables.countryCodes.items)]]

This blog is part of the series Visual Builder Cloud Service Learning Path. In this lesson we will look at consuming Fusion Applications REST services in a VBCS mobile application. In order to work...

Getting The Label/Description Value from a Select List in Visual Builder

When you add a select list component such as selectOneChoice to a Visual Builder page, you get a nice wizard that helps you bind it to data, and you can then easily access the value that you select in the list. However in some cases you might want to access the label of the list rather than the value. Here is a quick tip that will help you get there. Oracle JET introduced a new attribute to the oj-select-one component called value-option - this contains an object with two fields value and label that synch up with the list. Read more about this attribute in the JET Doc here. Right now there is no design time support for using this property in VBCS right now, but you can still leverage it. First create a page variable of type object and then add two string attribute in it called label and value. Next go into the page layout editor and switch to the code editor view and add the value-option option to your component (note that you should use curly braces):   You can now refer to the label using a syntax such as: {{ $page.variables.selectedVal.label }} For example this page: The Code would be: <div class="oj-flex">     <oj-label id="oj-label--490912658-1" for="oj-select-one--490912658-1" class="oj-flex-item oj-sm-12 oj-md-2">Select (One)</oj-label>     <oj-select-one value-option="{{$page.variables.selectedVal}}" options="[[$page.variables.airlineListServiceDataProvider]]" options-keys.value="id" options-keys.label="airline" value="{{ $page.variables.airline }}" id="oj-select-one--490912658-1" class="oj-flex-item oj-sm-12 oj-md-4" ></oj-select-one> </div> <div class="oj-flex">     <oj-label id="oj-label--490912658-2" for="oj-input-text--490912658-1" class="oj-flex-item oj-sm-12 oj-md-2">value</oj-label>     <oj-input-text id="oj-input-text--490912658-1" class="oj-flex-item oj-sm-12 oj-md-4" value="{{ $page.variables.airline }}"></oj-input-text> </div> <div class="oj-flex">     <oj-label id="oj-label--490912658-3" for="oj-input-text--490912658-2" class="oj-flex-item oj-sm-12 oj-md-2">Selected val label</oj-label>     <oj-input-text id="oj-input-text--490912658-2" class="oj-flex-item oj-sm-12 oj-md-4" placeholder="{{ $page.variables.selectedVal.label }}" value="{{ $page.variables.selectedVal.label }}"></oj-input-text> </div> <div class="oj-flex">     <oj-label id="oj-label--490912658-4" for="oj-input-text--490912658-3" class="oj-flex-item oj-sm-12 oj-md-2">selected val value</oj-label>     <oj-input-text id="oj-input-text--490912658-3" class="oj-flex-item oj-sm-12 oj-md-4" value="{{ $page.variables.selectedVal.value }}"></oj-input-text> </div>

When you add a select list component such as selectOneChoice to a Visual Builder page, you get a nice wizard that helps you bind it to data, and you can then easily access the value that you select in...

Oracle Visual Builder Cloud Service

Data Security and Role-Based UI in Visual Builder Applications

This blog is part of the series Visual Builder Cloud Service Learning Path. In this lab we will add some role-based UI based on groups in IDCS. We will also implement Data Security on our Expense Report business object. It's important before we go on that you understand the difference between data security and role-based dynamic UI. You need to do both to provide a secure app that has elegant usability. Data Security Data Security controls what data a user can fetch from the back-end. You can limit access to an entire resource - i.e. all Expense Reports - or define more complex rules for a resource - i.e. all Expense Reports created by me. Data security is enforced at the service endpoint so it's always secure and can't be spoofed by changing settings in your browser or changing the URL of the REST service being called. For business objects, you can define your own security rules at the object level. You can't set data security rules for fields in an object - i.e. only Managers can see the Salary field in an Employee object. For external REST services, you have to set the permissions at the service endpoints. There is no way to set additional VBCS-specific security rules over what the endpoints already specify. For many Oracle PaaS and SaaS services, like Oracle Sales Cloud or Oracle Mobile Cloud Service, you can define the security rules for the endpoints exposed. Role-Based Dynamic UI Role-based dynamic UI controls what components a user sees on a page. You can set restrictions on entire pages, or just on certain components in a page. For example you can hide the navigation button to a page or a tab. We use this expression to set component visibility by role: <oj-bind-if test=“$application.user.roles.role_name” > </oj-bind-if> Role-based dynamic UI is only enforced on the client. It is easy to go into the browser's developer tools and change the value of the user role. As such it alone is not enough to make a secure application - you must always use it with data security. So you hide the navigation to a page and make the contents of that page appear only to certain roles, but you must also secure the data returned on that page so that if someone spoofs the role the REST call only returns an empty data set. Updating Your Project This lesson builds on the Expense Report project we have been using in the VBCS Learning Path. If you are starting at this lab, go to Building Your First VBCS Application and follow the steps to import the project, then continue below. Download this ZIP file to your computer. In your project, click the menu in the top right and choose Import Resources. Drag and drop the ZIP file into the dialog. Select Delete existing files and resources and click Import. Setting Up a Role When you set up additional roles in your project, the roles map to groups in your IDCS account. Roles are defined at the project level and are available to all applications and business objects in the project. These roles act as additional roles on top of the standard VBCS "Authenticated User" role. We will talk more about what that means in the next section. For now, let's just set up a role. Open Project Settings in the top-right of the application window.   Click User Roles. Then click Create Role. Name the role Admin and click Create. In the Admin tile that was created, click Assign groups or users and in the Users section assign yourself to the group. Setting Up Data Security Now let's define data security rules on our Expense Report business object. We will it configure it so that: Authenticated User can only see their expense reports Admin user can see all expense reports So let's do that now: In the Business Objects panel, click Expense Report to open the Business Object Editor Click the Security tab in the editor, click the icon next to Role-based Security Select Authenticated User. The View, Edit, and Delete rows display below. Click the menu for each of these and select Allow if user created row Notice you can expand each node to see the exact query being checked for and add additional conditions to the query. Previewing the App as Different Roles The Page Designer has a Who Am I button  that allows you to preview the application in different roles. As we said, the Admin role is an additional role layered onto the Authenticated User role. But you can have different settings for all authenticated users and just Admin users. So if you want to preview the app as Admin, you have to deselect Authenticated User, even though Admin users are also authenticated users. Note that the Who Am I only spoofs the role in the UI and does not change the identity with which you call the services. Therefore, the Expense Reports REST calls will still return all the data that you - the currently logged in VBCS designer user - are allowed to see. Setting Role-Based View Restrictions on a Page You can set role-based permissions on a page or flow in the JSON metadata for the page/flow.  In the Web App panel, click the admin flow node to open the admin flow editor page.   Click the {} node to view the JSON for the page.  Enter the following code at the end of the JSON. Don't forget the comma at the end of the variable line:   "variables": {},   "security": {     "access": {       "requiresAuthentication": true,       "roles": ["Admin"]     }   } } If you run the page as a user who does not have Admin access, the Administration link no longer works Hiding the Navigation Link to the Admin Page Now we will set up a rule on the Administration link to make it visible only to people with the Admin role. In the Web Apps panel of the App Navigator, click root pages > shell. Click the source tab {} and under navDataSource.defaultValue.data delete the second object so that it looks like this:   "variables": { "navDataSource": { "type": "vb/ArrayDataProvider", "description": "The model describing the flows in the app", "defaultValue": { "idAttribute": "id", "data": [ { "name": "My Expense Reports", "id": "my-expense-reports", "iconClass": "oj-fwk-icon oj-fwk-icon-list oj-navigationlist-item-icon" } ] } }, Click the Events tab click Create Event. Select vbEnter event and click Next. Add a new Page Action Chain called setNavVisibility and click Select. Open the setNavVisibility action chain.  Drop an If action onto the action chain. Set the condition to: [[ $application.user.roles.Admin ]] Drag an Assign Variables action to the true path of the action chain. Click Assign in the Property Inspect. On the right side, select navDataSource > data. Set Reset Target to empty. Enter the following in the expression field:   [ { "name": "My Expense Reports", "id": "my-expense-reports", "iconClass": "oj-fwk-icon oj-fwk-icon-list oj-navigationlist-item-icon" }, { "name": "Administration", "id": "administration", "iconClass": "oj-fwk-icon oj-fwk-icon-list oj-navigationlist-item-icon" } ] Click Save. Use the Who Am I button to check that the nav link shows/hides correctly.

This blog is part of the series Visual Builder Cloud Service Learning Path. In this lab we will add some role-based UI based on groups in IDCS. We will also implement Data Security on our Expense...

Oracle Visual Builder Cloud Service

Adding a Navigation Bar to a VBCS Application

This blog is part of the series Visual Builder Cloud Service Learning Path. In this lesson we'll add a navigation bar to our application. First it's important to understand what actually gets loaded when you open a VBCS page in the runtime. Here is the heirarchy: index.html - this is the page that actually gets loaded. It's just a wrapper. The only time you'll need to edit this page is when you want to specify a different CSS file. shell page - this is the wrapper you see in the page. It contains the header and footer and the navigation bar that you will add in this lesson. You can have multiple shell pages for different parts of your application. The default shell is specified in the application settings (i.e. click Expenses node in Web Apps panel, then click the Settings panel). Like any other page, a shell page has its variables, actions, events, and so forth. flow - each flow specifies a top-level page and the application settings also specify the default flow to open when the app is accessed. Currently VBCS only allows you to navigate to the top level page of a flow or to another page inside the same flow. That means that any page that you want linked from the top-level navigation menu must be in their own flows. That's why we created the admin page as its own flow instead of a page in the main flow. Updating Your Project This lesson builds on the Expense Report project we have been using in the VBCS Learning Path. If you are starting at this lab, go to Building Your First VBCS Application and follow the steps to import the project, then continue below. Download this ZIP file to your computer. In your project, click the menu in the top right and choose Import Resources. Drag and drop the ZIP file into the dialog. Select Delete existing files and resources and click Import. Adding the Navigation Bar Open the Web Apps window and open Expenses > root pages > shell. Switch to the Code mode. Add the following code before the closing </header> tag: <div role="navigation" class="oj-web-applayout-max-width oj-web-applayout-navbar"> <oj-navigation-list id="123" aria-label="Choose a navigation item" navigationlevel="application" drill-mode="none" display="all" edge="top" selection="[[$page.currentFlow]]" class="oj-md-condense oj-md-justify-content-flex-end" on-selection-changed="[[$listeners.ojNavigationListSelection]]"> <ul> <li id="main"><a href="#">My Expense Reports</a></li> <li id="admin"><a href="#">Administration</a></li> </ul> </oj-navigation-list> </div> Creating the navigateToPage Action Chain Go to the Actions panel of the shell Page Editor Create a new Action Chain called navigateToPage. Go to the Variables panel of the Action Chain Editor. Add a String variable called page. Add a Boolean variable called navigate. In the Property Inspector for the page variable, check Input Parameters and Required. Do the same for the navigate variable. Switch back to the Action Chain view and drop an If action on the action chain. Set the Condition to {{ $chain.variables.navigate }}.  The reason you're doing this is that the selection change event can get dispatched from either a user action, like a click, or by external changes to the selection property. We only want to react to the former - user actions. We will set the navigate property below to ignore external changes. Drop a Navigate action to the true path of the If action. Switch to the Metadata View by clicking the { } tab and add the following lines in bold. Don't forget the comma at the end of the history line. "actions": { "navigateToPage1": { "module": "vb/action/builtin/navigateToPageAction", "parameters": { "history": "push", "page": "[[ $variables.page ]]" } } Adding the Listener on the Navigation List Go back to the shell tab and open the Events panel Click the + Event Listener button. Click the + button on Other Events and name your custom event ojNavigationListSelection. Click Select. Select the navigateToPage action chain and click Finish. The event is created. In the list of Events, click page under Input Parameters Set the mapping to be an Expression, then enter $event.detail.value as the mapping for page. Click navigate under Parameters. Enter $event.detail.updatedFrom !== 'external', set it to be an Expression, and click Save. The next lesson in the learning path is Data Security and Role-Based UI.

This blog is part of the series Visual Builder Cloud Service Learning Path. In this lesson we'll add a navigation bar to our application. First it's important to understand what actually gets loaded...