As a 4D developer, you may have already encountered a need to develop applications without a graphical user interface (GUI), otherwise known as a headless applications. Previously in 4D, this wasn’t entirely possible to do …. until 4D v18! In this blog post, we’ll go through some of the newly available capabilities so you can make your applications “headless”!
Why create headless applications? There are several use cases such as simulating Windows behavior on macOS, or having the Windows service behavior without using the service manager, and so on. But above all, it opens new opportunities such as developing bots with 4D.
How to launch a 4D application in headless mode?
You can now launch a 4D application in headless mode via the CLI (Command Line Interface) with the new “headless” parameter. Available for all application types: 4D, 4D Server, standalone, remote, merged applications. In the examples below, the current directory is the executable directory.
macOS examples (when terminal is placed in the “Contents/MacOS” folder of the bundle):
./4D\ Server −−headless MyDatabase.4DLink ./”4D Server” −−headless MyDatabase.4DLink ./4D −−headless MyDatabase.4DLink ./MyBuiltRemoteApp −−headless |
Windows examples:
“4D Server.exe” −−headless MyDatabase.4DLink 4D.exe −−headless MyDatabase.4DLink MyBuiltRemoteApp.exe −−headless |
We’ve added a new “headless” attribute to the object returned by the Get application info command. It makes it much easier to code depending on the execution mode: with or without interface.
Note: Now, when you run an application in service mode on Windows systems, it’s automatically executed as a headless application. Stopping the service quits the 4D application in the correct way (for example, using the “Quit” action in macOS activity monitor).
What happens during execution?
You may be wondering, “Okay, it’s fun, but what happens if a dialog was supposed to appear?” To keep you informed of what’s happening at runtime, 4D automatically activates the diagnostic logs when running in headless mode. The logs catch all user interfaces that could have been displayed and logs them with the [{applicationName}.HDLS] tag.
The general behavior is that 4D catches the commands that try to display something, logs a warning event with the name of the command and its call chain, and cancels the action. There are a few special cases:
- If no license is available, 4D logs this in the system event log and the standard streams, and then quits.
- If the database needs conversion, 4D logs this in the system event log and the standard streams, and then quits.
- If no available database or data file has been found, 4D logs this in the system event log and the standard streams, and then quits.
- When the debugger needs to be displayed, 4D logs an error and then simulates the “abort” action.
- When an alert appears, 4D logs and then simulates the “OK” action.
- When the QUIT 4D command is called, 4D logs and then simulates the “OK” action.
- When a merged application needs to be updated, a log is generated, the update is performed, and the application restarts in headless mode.
Example
For example, an ALERT command executed on a server run as a service on Windows will no longer stop the server execution. 4D automatically catches the command and writes a warning line in the Diagnostic logs. It looks like this:
11 2019-07-11 18:53:52 [myTestDatabase Server.HDLS] WARN – (Alert: Test alert label)[{“type”:”projectMethod”,”name”:”myTestAlert”,”line”:2,”database”:”myTestDatabase”}] |
This system has been created to help you see what happens in your headless applications, and improve your code (if necessary).
USING SYSTEM STANDARD STREAMS
We’ve added the new selector, Into system standard outputs, to the LOG EVENT command so that you can send a text to the stdout and stderr standard streams. As you may know, the LOG EVENT command has an optional “importance” parameter. So, depending on the event’s importance, the command will send the text to the stdout stream for Information message and Warning message, and to the stderr stream for Error message.
Send the text to stdout:
LOG EVENT(Into system standard outputs;"This is a text for stdout";Information message)
Send text to stderr:
LOG EVENT(Into system standard outputs;"This is a text for stderr";Error message)
You can also use redirections for the stdout and stderr system standard streams to retrieve information generated by 4D and your application. By default, these streams are generally directed to the console, rarely to the screen, depending on the system settings. For example, you can redirect the standard streams to files using the following command lines.
macOS:
./4D −−headless MyDatabase.4DLink 1>stdout.txt 2>stderr.txt |
Windows:
4D −−headless MyDatabase.4DLink 1>stdout.txt 2>stderr.txt |
Reminder for stream redirection combinations:
- 1>outputFile: the standard output stream will be written in the file instead of the system default output. The file is automatically created at command launch. If it already exists, old content is erased.
- 1>>outputFile: same behavior as the previous syntax, except that if the file already exists, it appends to the stream content.
- 2>errorFile: the standard error stream will be written in the file instead of the system default output. The file is automatically created at command launch. If it already exists, old content is erased.
- 2>>errorFile: same behavior as the previous syntax, except that if the file already exists, it appends the stream content.
- 2>&1: the error stream is merged with the output stream.
- 1>&2: the output stream is merged with the error stream.
Note: it’s even possible to use the open command to run a 4D package on a macOS system, the streams will be generated by this command and not the 4D application!
Conclusion
These new advances allow you to meet system requirements and also create new opportunities, such as bots. It’s up to you to combine this with your continuous integration (CI) and continuous testing (CT) channels for your software factory. Your only limit is your imagination!