5 Front-end API

The front-end API is all the facilities that run on the browser. This includes HTML, CSS, JavaScript, image files, etc. The Kiss back-end does not produce or modify HTML or JavaScript code. These files are served, unaltered, by the server as they are on the back-end disk. The Kiss model is that the browser receives these files from the server, and that they include all the code that the browser needs to perform its function. Besides these static files, all data is communicated between the back-end and front-end via REST services.

Having all of the display logic running on the front-end or user’s browser makes a lot of sense for the following reasons:

  1. Minimize the dependence the front-end and back-end have on each other. This means that one end can be changed without necessitating the need for the other to change. In other words, they are minimally dependent on each other.
    1. In this rapidly changing environment, minimizing dependencies means minimizing the amount of code that has to be changed as technology changes.
    2. Code is easier to understand and maintain since you don’t have four totally different languages in the same file.
  2. Push as much processing to the client side so that the back-end can scale easier.

All of this leads to the following:

  1. Shorter development time
  2. Easier to maintain
  3. Be most prepared for future changes
  4. Reduces server costs
  5. Reduced development time and cost

The front-end API is documented in the file manual/jsdoc/index.html.

5.1 Calling REST Services

On the front-end, the class Server is what deals with the REST communications between the front-end and back-end. In it, there are a handful of methods that deal with the environment, such as the back-end URL. All communications between the back-end and front-end are done with JSON.

The way it works is the login service requires a username and password, and it returns a login token (UUID). That token is used in all future calls, and it gets automatically invalidated after a certain amount of non-use time. There is no state kept on the back-end. Each REST call must login to the back-end with the provided token in order to be authenticated to communicate.

The method used to communicate is named Server.call(). It is passed the path to the REST service, the REST service method name, and a JSON object that is sent to the back-end method. A Promise is returned that is used to obtain the result of the call. This can also be used with async/await.

There is also a logout method that simply erases the login token so that future communications cannot occur.

The Server class also includes a method (fileUploadSend) that makes it easy to upload files.

5.2 Kiss Components

Although HTML provides what is needed for real applications, it provides those facilities at too low a level to be useful without a lot of custom code. Custom components (tags) allow you to encapsulate that advanced behavior into what is used as and appears as native functionality.

Kiss provides the ability to create your own custom HTML tags or elements as well as use those provided by Kiss. There are two principal user methods that make this work. Utils.useComponent is used to load either a Kiss defined component or one you define yourself (there is no difference). This loads the JavaScript file that defines the new tag. All of the components that come with the Kiss system are under the src/main/frontend/kiss/component directory. You can see those files for examples of how custom tags are defined.

New application pages are loaded with the Utils.loadPage method. In addition to loading the HTML and JavaScript code associated with that page, this method performs the processing necessary to make the components work. It does this intelligently so that, for example, one component can use another component without any special loading order requirement.

Briefly, the code that describes the custom tag must describe what the tag is replaced with. Ultimately, it must boil down to straight HTML, CSS, and JavaScript code.

5.2.1 Tagless Components

Let’s say you have a pop-up window that allows a user to search for employees, products, or whatever. The user gets a variety of search capabilities and the selected item is returned. Let’s further say that you need this functionality in several places within your application. These are tagless components. They aren’t placed with a custom tag. They are a response to an event like a button push. Tagless components allow you to encapsulate a block of functionality (including pop-up windows) into a neat package that can be reused in any number of places.

The method used to load tagless components is Utils.useTaglessComponent. Later, when the tagless component is needed, one would execute Kiss.MyComponent.run(in_data, on_exit) (where MyComponent is the name of your tagless component). in_data represents possible data passed to the component on entry. on_exit is a function that gets executed when the component exits. Arguments passed to on_exit are determined by the component.

5.4 File Uploads

Kiss includes facilities that make it easy to upload a file or multiple files. The way to use it is as follows:

The HTML would contain two controls: a file input and a button. The file input looks as follows:

<file-upload id="the-file">Upload File</file-upload>

The button is just a standard Kiss button. In this example, its ID is “upload”.

The file input control allows the user to select the file or files to be uploaded. If multiple files are to be allowed the multiple attribute should be added to the HTML.

The button is used to activate the upload process. Your code that sends the file(s) to the server should be attached to this button.

The file-upload control contains the helper functions numberOfUploadedFiles and getFormData, and the main function used to send the files is fileUploadSend in the Server class. The code would look like the following:

   $$('upload').onclick(async () => {
        if ($$('the-file').numberOfUploadFiles() < 1) {
            Utils.showMessage('Error', 'You must first select a file to upload.');
            return;
        }
        const fd = $$('the-file').getFormData();
        let data = {
            var1: 22,    // just some random data we want to send to the back-end
            var2: 33
        }
        const r = await Server.fileUploadSend('theService', 'theMethod', fd, data);
    });

Back-end code would look like this:

public void theMethod(JSONObject inJson, JSONObject outJson, MainServlet servlet) throws Exception {
    String var1 = inJson.getString("var1");
    String var2 = inJson.getString("var2");
    if (servlet.getUploadFileCount() == 0)
        throw new Exception("No file specified.");
        
    String originalFileName = servlet.getUploadFileName(0);
    
    
    BufferedInputStream bis = servlet.getUploadBufferedInputStream(0);
    // do something with the file stream
    bis.close();
    
         // or
         
    String localFileName = servlet.saveUploadFile(0);
}

5.5 Utilities

Kiss includes an ever-growing set of utilities to help deal with common tasks. These utilities are located under the src/main/frontend/kiss directory and have names such as DateTimeUtils.js, DateUtils.js, TimeUtils.js, Utils.js, etc. These utilities are documented in the front-end API documentation.

5.6 Controlling Browser Cache

Browsers have a mind of their own in terms of deciding when to use their cache for a file and when to download a new one. This can cause no end of trouble when code gets changed. Some user files end up being old from the browser cache, and others are freshly downloaded. The old and new files don’t agree with each other and all sorts of errors occur.

Kiss includes a facility to assure that all files are downloaded afresh whenever the application changes while still taking maximal advantage of the browser cache when the files have not changed. The only cost for this capability is the requirement that the index.html file always gets loaded afresh. To that end, Kiss has code to ignore browser cache and always load index.html afresh.

index.html contains two variables named SystemInfo.softwareVersion and SystemInfo.controlCache. Assuming SystemInfo.controlCache is true, Kiss has code that forces the browser to reload all files whenever SystemInfo.softwareVersion changes. After the code is re-loaded, the browser cache will work as normal to maximally cache the files until the next SystemInfo.softwareVersion change.

5.7 Additional Resources

Although not a part of the Kiss system, there are some very valuable technologies and libraries that have been used with Kiss in order to create some very powerful solutions.

The first is the Lovefield library, which adds SQL capabilities on the browser side. Data is persisted on the user’s browser and remains through browser or machine reboots. The library is located at https://github.com/google/lovefield

A recent technology that has been used to enable browser applications that run when there is no Internet connection is called Service Workers. There is a package at
https://developers.google.com/web/tools/workbox that makes working with service workers very easy.