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 files. The HTML uses a <file-upload> control, and the Server.fileUploadSend() method handles the transfer to the back-end. The file-upload control provides helper methods such as numberOfUploadFiles() and getFormData().

On the back-end, the servlet provides methods to access uploaded files: getUploadFileCount(), getUploadFileName(), getUploadBufferedInputStream(), and saveUploadFile().

See the included example application and the Kiss book for complete front-end and back-end file upload examples.

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 Client-Side State Persistence

Application state that must survive page navigation and browser reloads is kept in a single client-side store named AppState. The login token is not treated specially; it is simply one reserved entry stored alongside any other front-end state. AppState is the only part of the system that accesses the browser’s Web Storage directly.

By default each browser tab is its own isolated session: state survives a reload but is not shared between tabs, so two tabs never overwrite each other’s data and a new tab requires its own login. This behavior is configurable (per-tab, shared across all tabs, or in-memory only). Data passed between screens (Utils.saveData and Utils.getData) is also kept in AppState, so it too survives a reload.

Because the token persists, a reloaded or deep-linked page resumes the existing session automatically. When the back-end is restarted, however, its in-memory sessions are gone; Kiss detects this and asks the user to log in again rather than resuming onto a dead session.

5.7 Client-Side Routing

Kiss gives each screen its own URL through a hash-based router (Router). Because routing happens entirely in the browser by way of the URL hash (for example #/customer/123), it requires no server-side URL rewriting and behaves identically on the development server, file://, Tomcat, and Electron. Each screen becomes deep-linkable and bookmarkable, and the browser Back and Forward buttons navigate between screens.

Routes are declared in the application file src/main/frontend/routes.js. A route may carry path parameters (for example :id) that the target screen can read. Screens that need no special handling require no entry at all: with file-based fallback enabled, a URL matching no declared route is loaded as a screen of the same name from a configured root directory.

Routes that require a logged-in user (the default) are guarded. A deep link followed while logged out is redirected to the login screen, carrying the requested location, so that after authenticating the user lands on the page they originally requested.

5.8 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 that forces every downloaded file to be re-fetched whenever the application is upgraded, while still taking maximal advantage of the browser cache when the files have not changed. It is driven by a single version number and requires no server configuration, so it works on the development server, file://, Tomcat, and Electron alike.

The version lives in index.html, which is the one file Kiss keeps perpetually fresh. Because index.html is always current, its version is always current, and every other file the application downloads is requested with that version appended – so a single change to the version forces all of them to be re-downloaded. Once the new files are loaded, the browser cache works as normal until the next version change. When a production WAR is built, Kiss stamps a fresh version automatically, so every release force-refreshes all clients with no manual step. During development the mechanism is turned off, so edited files are seen immediately on reload.

5.9 Browser Security

Kiss delivers a Content-Security-Policy together with a set of standard security response headers (clickjacking protection, X-Content-Type-Options, Referrer-Policy, and, over HTTPS, Strict-Transport-Security) on every response. The Content-Security-Policy restricts where the page may load scripts, styles, images, and network connections from, which closes off the most common cross-site-scripting attacks.

These headers are added by a filter that ships inside the application WAR and registers itself automatically, so no servlet-container (Tomcat) configuration is required. The supplied policy already accommodates the Kiss front-end; an application that introduces a new external origin (for example a separated production back-end) adjusts the policy in one place.

5.10 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.

For in-depth coverage of the front-end component system, grid integration, popup windows, and utility classes, see the Kiss book.