For embedded developers, knowing about application servers can save you a lot of time. For many developers, web application development is a whole new ball game. Common misperceptions can lead to frustration and much longer development time.
|Web Server||App Server||Example|
An application server’s primary job is to provide its clients with access to what is commonly called business logic, which is code that executes at the server side for each request/response pair. The business logic may produce dynamic content as part of its response. Communication between the application server and its clients might take the form of HTTP(S) messages, but this is not a requirement. Application servers can typically manage any type of message transfer, including WebSockets and many other protocols.
A typical web server has one role: to implement the HTTP protocol. This protocol activates a browser to issue a request that a server can respond to. Today’s web is highly sophisticated, featuring elaborate graphics and streaming media, yet surprisingly, the HTTP is a very simple protocol. All it does is transport requests and responses.
Because HTTP is a stateless protocol, there is no intelligence in the operation: no decision-making, no context, no scripts, and no code to execute. There is also no dynamic page creation to make user interfaces slick and easy to use. If a page needs to be dynamic, some other program has to do that work and put the result where the web server expects it to be.
POST is used to submit data from the web browser back to the server. This is the request that is generated when someone hits the "Submit" button on a filled-out form. A basic web server cannot process a POST request, since it will have no idea what to do with the data in the request. It must rely on some other program or utility to process the data.
On older standard websites, that utility might be a Common Gateway Interface (CGI) plug-in: the web server would simply hand any POST requests over to be handled by CGI. While CGI isn't appropriate for most embedded applications due to its size, performance, and inability to exist in a monolithic architecture, the fact remains that the web server needs something else to handle data returned by a web browser (Figure 2).
Most web-based applications need much more than this. In particular, embedded web applications generally must be able to let the web functionality affect the device operation - the remote browser has to be able to "talk" to the system. A web server has no such capability, so everything beyond the simple processing of HTTP must be written as a part of system development.
The low-level code that will interact directly with the system hardware will likely be written in C, and, because these routines are so system-specific, they will need to be written during development no matter how the web connectivity is implemented. The challenge is that a web server has no way of accessing those routines, meaning that some way of connecting the two must be built.
The two high-level elements that must be created are:
These two functions sound deceptively simple. Conceptually, they are simple, but the details of what effectively amounts to a translation from a web conversation into device action are tedious and error-prone. Developers frequently underestimate the amount of time required to produce this code by a wide margin. For this reason, using only a basic web server will result in months of additional coding. You end up spending many weeks of time working on nitty-gritty details, things that an application server framework has already put in place.
Application servers provide that missing link, delivering configurable functionality that makes the connection between the simple HTTP operations and the complex matters the application needs to deal with. This low-level generic work is already done, and coding can focus on adapting the requests and responses to your specific technology.
Application servers build onto web servers a much broader range of configurable functionality. At the very least, they provide a way for the web server to hand off tasks to any of a variety of plug-ins that can handle requests for things other than simple resources. This means that an application server will allow real-time decision making and business logic, invoking other scripts or programs and, if appropriate, dynamically creating response pages in real time.
Most importantly for developers, however, is the fact that application servers tend to come with complete frameworks for use in developing code for the system. For example, if only a web server is used, then one must write custom code for recognizing and parsing requests and generating responses for functions being handled outside the web server. By contrast, the framework accompanying an application server will typically have a library that includes request and response objects. The low-level generic work is already done, and your coding can focus on adapting the requests and responses to your specific technology.
Each application server may provide a different set of resources targeted for its targeted programming environments and languages. While C is familiar to many systems engineers, and is generally better for low-level code, there are higher-level languages that simplify the programming and eliminate the need to handle numerous low-level details.
Real Time Logic's Barracuda Application Server is a good example of an application server designed specifically for use on deeply embedded systems. It supports the Lua scripting language and its associated Lua Server Pages, providing a dramatic speed-up in code development. You can learn more about Lua in the Lua Whitepaper.
Figure 4 illustrates the elements provided as a part of the Barracuda Application Server product. The application server can handle C/C++ code in addition to Lua programs. Support for different plug-ins, secure transactions, various types of I/O and file storage, and even database functionality are included. Greater transportability is afforded by an API that remains consistent between different operating systems.
The differences outlined here between a web server and an application server apply in most cases, although, over time, the boundaries between the two have begun to blur. Typical basic web servers are more likely to focus on HTTP, while others may add a few features that were once associated only with application servers.
As an example, if all you need is a way to connect a web server to C/C++ functionality, the Barracuda Web Server provides web server capability and a C/C++ application framework for invoking C and C++ programs. While C programs (server business logic) take longer to develop and require that the server be taken down and restarted for updates (as opposed to Lua-based application server programs that are compiled on the fly), they do remain an option for embedded systems having limited web connectivity requirements.
The following video shows how an application server with an integrated scripting language can be used to develop modern real-time web based user interfaces. You may run the same setup as shown in the below video on any suitable ESP32. The code can be found on GitHub and installation/compilation/upload instructions can be found here.
Web servers and application servers both offer a way to provide an embedded system with an Internet presence. The difference lies in the amount of programming required to adapt the server to the system. Classic web servers simply process HTTP requests and responses; anything else must be developed from scratch. Much of that work amounts to spending time and money "reinventing the wheel" for common functions and infrastructure that aren't supported by a web server.
By contrast, application servers include frameworks that dramatically shorten the development cycle. Choosing an application server means that you don't have to write commonly-used communication and user interface functions or their underlying infrastructure for each system. Programming resources can instead be focused on functionality that is specific to the system.
Since HTML is text based, a lot of work is required for: managing data, parsing requests, and assembling responses. All of this needs string manipulation. String manipulation in C isn’t rocket science, but it’s tedious and extremely easy to get wrong. Everything must be strictly typed, and memory must be explicitly reserved and released as needed, requiring scrupulous attention to every detail and making maintenance difficult.
On the other hand, with Web scripting environments such as Lua, much of this work has already been done. The application server abstracts the web server details, giving access to request and response objects and their associated APIs. This means that the application specific code has to deal only with high-level behavior and data.
A single line of script can implement the entire string concatenation. The lower-level machinations are automatically handled. Scripts also access and manipulate data without the need to worry about data organization or type definition.
Another important distinction is that scripting languages use just-in-time compilation while the system is operating. Whenever the user navigates or refreshes the browser, the virtual machine compiles any changed script before it sends the requested page to the browser, thereby automating the host of compilation, linking, and other developer overheads associated with an equivalent C-based application.