Client-side triggers for server-side validation errors
Blog by Barbara Douma
Dynamic server pages already support client-side field syntax checks, which prevent incorrect data from being submitted to the server. Uniface provides a default mechanism for reporting and displaying syntax errors in the browser, and web triggers for customizing the error reporting and display.
However, field syntax checks are just a subset of the data constraints that Uniface validates when it is instructed to reconnect, store, or validate data. Other declarative constraints as well as procedural constraints are validated on the server and, until now, there was no customized way of reporting such errors in the browser.
With Uniface 10.3.02.019, Uniface introduces support for server-side validation error reporting for fields.
- Default formatting and error reporting for fields that are in error and visible in the browser. This is the same mechanism available for client-side syntax errors: the -ufld-highlight-error- style and uflderror bound error element.
- New showError and clearError web triggers, which enable you to customize error display and reporting. These triggers are defined on fields in the component structure and they are executed in the data layer of the client. This means they can be executed for fields in error, even if the field is not in the layout, is in a hidden view, or is no longer available in the browser.
When you define a showError trigger, you need to define a corresponding clearError trigger. For example:
To see this code in action, you can download a new sample from Uniface Samples. In addition to this code, which uses Field.setProperty(), the sample demonstrates the default error display, the use of this.getBoundElement()to navigate and style other elements in the DOM, and the use of an error count and error list to display multiple errors.
For more information, consult the documentation:
Blog by Peter Lammersma
For today’s businesses, they say, data is more important than ever. I don’t agree with the ‘today’ part: data always has been businesses’ most important asset, and always will be. There is a difference between now and back then, though. The IT landscape is now extremely dynamic and reliant on innovative IT. Dependence on technology leads to enormous growth of data and, at the same time, of the number of attacks on the data.
Can a potential risk be turned into a business opportunity? During our second workshop / ‘pizza session’ of 2019 we answered that question. Before I explain how, we need to look at the cause of the growth of security problems. Although we all think security problems will never happen to us, investments in security were never higher than they are today. Return on security investment is one of the key figures that management uses to steer the business.
We feel safe with ‘good old’ client/server, with all the visible security measures: it’s like having a barrier to the carpark, a security guard near the entrance and a kind but resolute receptionist. Contracts and non-disclosure agreements must be signed, and sometimes employees must have a certificate of conduct. Before one can even start working with the application, passwords on computers and networks are mandatory. And, on top of all these safeguards, you and I have created the best authorization and authentication algorithms in the world!
Within this ‘fortress’, it feels as if the data is safe inside the organization walls. But it is not, despite all the visible and invisible security. According to ‘IBM 2016 Cyber Security Intelligence Index’ more than 60% (!) of all attacks on data have an internal cause. These are people you trusted! Did they break through all the security precautions? Are they spies? Criminals? The reality is less exciting, but just as frustrating. In most cases, the problem is just that the innocent users of the application opened an attachment that they should not have opened.
All the effort in securing the building, the network infrastructure, the workstation, the database, and the application has lost its value because of one detail: the connection to the data(base). Once you know how to get to the data, there’s not much that can stop you. Compare it with a defensive wall that loses its value with every hole. The connection from the client to the database looks like a tunnel. A long tunnel, perhaps, but at the end you see the data as shining gold.
It doesn’t matter what technology is being used on the client. Every technology has its ‘holes’. Criminals are not interested in any of the secure parts, but in that one single thing that is not: SQL injections, readable connection strings in assignment files, data source names from your ODBC or SQLNet. Allowing direct access to the data is a risk. Somewhere in the application, a connection string to the database must be available. As soon as this connection string can be found on the computer, all other security has lost its value.
Even the size of the application is irrelevant. Let’s assume you have a web application with hundreds of DSPs. From a user’s perspective there is no direct connection to the database. But what if this application also has one or two forms for maintaining a table? Then this can be the rabbit hole leading to your data. As we learned in the pizza session, prevention is better than cure, so let’s see what can be done to plug this rabbit hole.
Multi-layer versus multi-tier
It’s not client/server, per se, that causes the problems. It’s the way it is used. Traditionally, client/server is two-tier: the client for presentation and the server to store the data. But an application is more than just presentation and data. The real value is in the business rules and the business logic. By the way, those are not the same! I have seen a lot of applications that claim to be multi-tier (multi > 2 😊), but they are multi-tier in name only. They are really only multi-layer.
So what’s the difference between multi-layer and multi-tier?” Multilayer is separation in the application’s logic. Services for reading data, services for business rules, reports, forms, etc., are layers. Using multiple layers in the application structure is a very good habit, but it does not do anything for security.
Multi-tier, on the other hand, is a technical separation. It allows the application to run its processes on several machines: the presentation layer on the client, the business logic on an application server, and the business rules on the database server.
The fun part is that Uniface allows us to move layers into tiers – without changing our coding! At least, you can if you’ve used the layers consistently. In the pizza session we worked on this concept.
Moving data access to a server
The starting point of the pizza session was a typical client/server application: all the processing on the client and all the data on a server. Take a look at Figure 1: you’ll see a Uniface application on the client with two form components and one service. Reading and writing is done in the components.
In the worst case, the assignment file has one of the following path settings:
· $DATA_DBMS_MQL = MQL:server:database|username|password
· $DATA_DBMS_TLS = TLS:server+port|username|password|database
· $DATA_DBMS_MSS = MSS:DataSource:database|username|password
· $DATA_DBMS_ORA = ORA:t:host:database|username|password
You might have secured everything, but the connection string to the data is readable in the assignment file. This means your data is as open as it can be! The technology that is used to connect to the data is not relevant, nor is the security of the connection, application or network.
A setup like this is only fine for development purposes – with fake data.
In my Uniface career I have seen hundreds of applications, and a lot of them had the database details in assignment files on the client, even in production environments. Having the connection string data in a readable format in the assignment file makes it pretty obvious. Using the Uniface PathScrambler makes the connection strings unreadable. That feels a bit safer. But remember that somewhere in the process, the connection string must be unscrambled. That information is stored in memory and so it can be found with the right tools.
It’s a good habit to use a service for reading and writing to the database. In the pizza session, we changed the application in Figure 1 to something like Figure 2.
The normal behavior of the Uniface read process is, as we all know, activating the retrieve trigger. Uniface then invokes the read trigger to read and fetch the data from the database. To change this so a service can be used to read the data, an operation on a service must be called. On the form for the entity, the ‘Data access’ property is set to ‘non-database’.
Advice: create subtypes for all modeled entities. Have one subtype that allows database access and another subtype that is non-database. The first can be used on a service that does the reading and writing. The other can be used on the client to display the data.
At this point, two things are achieved:
1. The application uses a service to read and write. Officially, the application has a Service Oriented Architecture.
2. The application is multi-layer.
So, we’ve scored points! However, from a security perspective nothing has changed. As shown in Figure 2, there is still a direct connection from the client to the database.
But now take a look at Figure 3. The only thing that’s changed is the execution of the service. For a Uniface developer, this is just a small step:
1. In the assignment file on the client:
a. All connections to the database can and must be removed;
b. Replace them with a path to the server:
$TCP_EXEC = TCP:servername+port|username|password|pizza_2_exec
* = $TCP_EXEC:*
2. Install URouter on the server. In the URouter’s assignment file:
pizza_2_exec = userver -asn=pizza.asn -dir=path -adm=path
3. In the assignment file (in this example pizza.asn), add the connection string to the data.
Now, when the service is activated from the form, the processing is executed on the server – without any modification to the application! Suddenly the application is multi-tier.
Why is this more secure? From now on, when someone tries to look into the metaphorical tunnel between client and server, there is no shining gold data but just a Uniface UServer-process. There is no direct access to the database. It is impossible to send SQL requests to the database on the server, because there is no direct access to the database.
From here on, it is up to developers like you and me. The only way to access the data on the server is by requesting data or submitting a change to a Uniface service. With our development skills, we can secure this data: it’s just a matter of authentication and authorization.
But there is more!
In the workshop/'pizza session', we played with the configuration. The data is safely hidden behind a service. The only possible way to read the data is by calling the service from the Uniface form components. But what if you want to be able to read the data with other tools?
It’s highly advisable to implement all your business rules in services and execute these on a server. So, now you have your data and the business rules on the server. Let’s suppose that, although you’re happy with your Uniface desktop application, you also want to be able to make the data available to an external system, or you want your data to be part of a mobile solution.
As soon as you have your most valuable assets (business rules and data) executing on the server, you can access them with any technology you want. Look at Figure 4. By adding a webservice to the configuration, all of a sudden, the Uniface service can be used by and/or in any other technology!
In just a few steps, a potential risk can be turned into a huge business opportunity.
When you started reading this article, your data felt secured but in reality it wasn’t. With a few changes in the Uniface configuration your data is very secured. And, at the same time, you created a new business perspective because the data can be made available to third parties in a way that you can control.
To summarize, the steps are:
- Stop reading and writing in the presentation layer
- Implement services that do all the reading and writing
- Move the execution of these services to the server
- Add webservice functionality to the services
If you want advice about the level of security of you application or need any help with the configuration of your deployment environment, you can always contact me. In the next Blog/pizza sessions, we will take a closer look at the fourth step and beyond. Trust me, with Uniface you can do anything.
Utilities for Uniface 10
Modern application development environments need to allow close integration of customer or community tools and utilities, to further enhance developer productivity. The IDE, delivered with Uniface 10, enables closely integrated extension through user defined worksheets and menu options.
Many of you know that the Uniface Support team often creates utilities to automate or simplify some our day to day activities. With the new user defined integration, we have an ideal way of making these available to the community so have collected a number of these utilities, mainly enhanced versions of components found in the Uniface 9 IDF, together and packaged them up for anyone to use.
What is included in this toolkit?
- Create Referential Integrity
- XSLT Workbench
- Global Search
- Cross Reference
- Copy user data from entity editor
Create Referential Integrity
Generate SQL scripts for maintaining referential integrity within the database
The XSLT Workbench is a tool for creating and testing XSLT stylesheets.
Global (Proc) Search
You can use the Global Proc Search dialog to search for commands, expressions, and operands in all Proc. It now also features a button that allows to directly open from the search result the related Code Editor.
Cross Reference Viewer
With the Cross Reference Viewer you can generate reports from the data of the cross-reference table. It now also allows you to directly open the related Code Editor from the cross-reference search results.
The different utilities can easily be accessed from the Main Menu ( ≡ ) of the IDE.
The Uniface 10.3 IDE Additions project also includes an extra menu item for the Entity Editor that allows you to directly export the user data of the entity. This can be seen as a partial replacement of the Convert Data utility of the version 9 IDF.
Work in Progress
We still plan to add more features to the Uniface 10.3 IDE Additions project - so this is very much “Work in Progress”.
And the good news is that we are not going to keep this stuff to ourselves. The Additions can be downloaded from here (Uniface utilities, addons and extras). And in order to get the utilities working you just need to include the additions.asn at the top of your (or the default) ide.asn.
We hope the Additions utilities are helpful,
Uniface Customer Support
Please note, that although the utilities are uploaded by the Uniface team, it is made available as-is and is not in any way part of the regular Uniface product. Therefore the rules and regulations for Uniface maintenance and support do not apply to the Additions utilities.
Blog by Peter Lammersma -
Recently, a dozen Uniface developers gathered at Uniface headquarters in Amsterdam. Some of them had driven for several hours to be here on time.
What was so important about this meeting? The answer is that these developers represent several organizations with one thing in common: they all trust Uniface for their most vital and business-critical applications. Something else the organizations have in common is that they all want to migrate to Uniface 10. That’s why they sent their developers to learn more about it.
A few weeks earlier, most of these developers had participated in a webinar where I told them about the major changes and enhancements in the latest version of Uniface. So, they had heard and seen a lot about these changes already, but on that particular evening in April it was time for some hands-on experience. As a well-known Uniface expert and business partner, I had been asked to guide my fellow developers through this process, and we had decided that ‘pizza session’ was a good name for it (more about this choice below).
The name reminds me of some evenings in my past. Software, cold pizza, and warm cola; what more does a developer need?
The evening consisted of three parts, starting with an optional slot for configuration support. Beforehand, the participants had received instructions on how to install Uniface on their notebooks and create a development environment. If they had run into problems, they were invited to arrive early so we could help them with the configuration. As luck would have it, someone did show up during this pre-pizza config support part of the evening. No, he didn’t need help, though – he just had a three-hour drive and loved to be on time.
According to Mr. Maslow and his hierarchy of needs the second part of the evening was the most important. It’s obvious that in 1943, when he published his theory, software as we know it had not yet been invented. Nevertheless, everybody enjoys pizzas. Thirty minutes later, a dozen pizzas had completely disappeared, leaving the same number of developers eager to start.
The third and final part of the evening was the hands-on bit. At the back of the classroom, Ton Blankers, Uniface account manager, and Gerton Leijdekker, software architect, were present to answer any questions I couldn’t handle. I kicked off with some theory – just enough for the participants to get started. For the next two hours, a classroom filled with software developers worked on a couple of assignments.
This pizza session was all about the changes to the Uniface 10 IDE. I can talk for hours about these, but as I was limited to a 30-minute timebox, I focused on the major changes – for instance:
- The terminology. What is a Main Development Object?
- … and how is it related to the editors in Uniface?
- What is the difference between Templates, Objects and Models?
- … and is this really different from what we are used to?
- What is the Compiled Modules Inspector?
The assignments were about enhancing the IDE with your own utilities. In three exercises, the developers created User Defined Worksheets and User Defined Menus. They learned how to use the IDE in Uniface 10. But the assignments were also about the changes in the meta dictionary to gain full control over the IDE.
Was it a successful evening? Everybody was able to install and configure Uniface 10 (which takes no more than 5 minutes), the pizzas were great, and everyone finished the exercises. But most importantly, the developers discovered themselves why Uniface 10 is so much better than all previous versions. And now they believe it is time to migrate to version 10.
We at Uniface were more than satisfied with the outcome of the very first pizza session of 2019. The security guys were curious, though: what was everyone so happy about? Mission accomplished.
Why do we call it ‘pizza session’? Uniface is just like pizza. Everybody loves it. It’s convenient. And with the right basis (the bottom), everything is possible. Used as a plural, pizza sessions, it is a reusable concept. Yes, we want to organize these sessions a few times a year. There is so much more to discuss and learn about Uniface. The next pizza session is planned for June.
Blog by Barbara Douma
Since the introduction of Uniface 10.3, we have been rolling out a feature called smart suggestions, which adds search and filtering functionality on the basis of object name and description. This makes it easier and faster to find an object that you want to open, edit, or use in a given context. As you type a keyword or part of an object name, the Uniface IDE provides a list of suggestions for objects that match the provided string and are appropriate to the context.
Smart suggestions were originally introduced on the Main U-Bar in Uniface 10.3.01.012 (see the blog Smart Suggestions in the Main U-Bar of the IDE). Since then, we've added this feature to the Component Editor when editing name-based properties. You get smart suggestions when you:
· Rename entities, fields, and labels in the Component Editor (10.3.02.001)
· Define the Modeled Component and Bound To properties in a derived component (10.3.02.002).
Now our focus is on the Resource Browser, starting with the Component Editor. As of Uniface 10.3.02.008, the Uniface IDE provides suggestions in the Model tab, so that you can easily find the modeled entities and fields that you need to use.
Resource Browser: Model Tab
The Model tab of the Resource Browser has been redesigned. It now includes a U-Bar that can be used to find and filter the modeled entities displayed in the tab. The list of entities includes subtype (specialization) entities. Icons indicate whether an entity is a normal modeled entity ()
or a subtype entity ( ).
To ensure fast performance, a maximum of 50 objects can be displayed. You can override this by clicking Show all, or configure to a different maximum using the UBAR_RESULTS_MAXHITS logical.
Suggestions for Modeled Entities and Fields
Instead of browsing through hundreds of entities, just start typing a string that occurs in the object name or description in the Model tab's U-Bar. As you type, the list is filtered to show only matching entities and sub-entities.
As usual, suggestions are offered in the following order:
1. Objects whose name starts with the entered text
2. Objects whose name contains the entered text
3. Objects whose description contains the entered text
You can scroll through the list of suggestions using the Up and Down arrow keys or the scroll bar.
To insert an entity into the component structure, highlight the entity in the list, then drag and drop the entity into the component structure (or draw the entity frame for a form or report component.)
To add the entity's fields to the component structure, you first need to select the entity—highlight the entity in the Model tab and press Enter, or double-click the item. This copies the entity URL to the U-Bar and, by default, displays the entity's fields. (Notice that the fld: code is appended to the URL.)
What if you selected an entity to display its fields before you inserted the entity? No worries. Just right-click on a a field and choose Parent Entity from the context menu.
The parent entity is then displayed in the Model tab so you can highlight and insert it.
Suggestions for Parent or Subtype Entities
As you saw already, subtype entities are easy to recognize in the Model tab, but you can also find the parent or subtypes of a given entity.
For example, to get the supertype of a subtype entity, right-click the subtype in the Model tab, and choose Parent Entity.
You can also use the context menu to show the subtypes of an entity. For example, the following suggestions are shown when you choose Subtype Entities for the UTREE_PERSON.UTREE entity:
Notice that the ent: object code has been added to the entity URL.
If you now select one of the subtypes, the complete URL, including the supertype is copied to the U-Bar and its fields are displayed:
Navigation Using the Object URL
If you want to return to the supertype object, you can click on the object's name and press Enter. In fact, each element of the URL is like a button that can be clicked to navigate up the object URL.
When you select an object name, a list of the subobject types is displayed. For entities, these are ent: for subtypes and fld: (the default) for fields.
We hope you will enjoy the Resource Browser improvements that we have introduced so far.
But it doesn't end there! As of Uniface 10.3.02.009, smart suggestions are provided in Model tab of the Entity Editor when you add modeled entities to a relationship, and in the Project Editor when you add create derived components from a modeled component. The principles and behavior are the same as in the Component Editor.
Recently, we had the presentations of the first Creative Sprint and let me tell you it was a great success. I’ll start by taking you back in time while sharing what are the thoughts which drive this initiative.
The Uniface’s lab is still a startup, yes! A 35-year-old startup in that sense. As with all startups, we thrive through the innovation that comes from the brilliant minds that continue to form the Lab throughout these years.
When working on technology, one tends to adapt the new high-tech trends to produce business value. This is a creative quirk. This challenge rewards the individual with satisfaction and fulfillment. To maximize the benefit from such experience, one repeats the process with certain periodicity, making it part of the development process.
In general, Agile is associated with a creative/iterative development process, following that line of thought, it is common practice in technology minded organizations to include a moment to trigger the creative spirit and embed it on the execution cycle of the production of software. Additionally, that moment serves as a source of wisdom to individuals who use that time to attempt new ways, find new ideas, discover new possibilities.
At the Uniface Lab, we are no different. Already for a few years, we have been trying to stimulate this inspirational flare in between our regular sprint schedule. To spark imagination a bit more, we have adopted a Creative Sprint; a one-day sprint where the goal is to ignite curiosity, play with new ideas and have fun.
Our creative sprint is also a welcome break in our tight schedule. A break which is an investment too. A break as it allows us to step out of the production harness and an investment because it spawns our technological paraphernalia (ideas and tooling).
As competitive as we are, we want to deliver the outmost in one day, producing great value for our time. To illustrate that, I want to share some of the ideas from the creative sprint:
The results were astonishing, a lot of enthusiasm and tons of valuable information which serves as food for thought. All in a very short span of time. Besides there is more to come as we get a chance to spend some time on innovation every two weeks. How great is that!
Blog by Jyoti Singh
The purpose of this blog is to inform you about some changes in the way widgets are documented and described.
Widgets are the elements that enable the user to interact with a Uniface application. In Uniface, we recognize two types of widgets:
· Physical widgets are the implementations that provide the functionality to the user. They vary depending on the underlying GUI technology.
· Logical widgets are named configurations of the physical widgets. Developers can configure physical widgets to use specific properties/styles to create their own logical widgets. Consequently, one physical widget can be referenced by multiple logical widgets. The available widget properties are dictated by the physical widget, and it is the physical widget that knows how to interpret properties. Logical widget definitions are defined in the [webwidgets] and [widgets] sections from the initialization file.
The logical widget definitions are available to the Development Environment (IDE), where they are shown in the Widget Type property for entities and fields, allowing developers to select one for use. By default, a Uniface installation provides a default set of logical widgets , but this set can be customized by the developer.
The logical widgets used in the application must also be made available at runtime via the [webwidgets] and [widgets] sections from the initialization file in the runtime environment. Forms, Reports, and Dynamic Server Pages (DSPs) use this mechanism.
With the introduction of the physical widget HTMLINPUT for DSPs, which can be used to specify very different input elements, the emphasis is moving more and more towards the capabilities of the physical widget rather than the logical widget. To reflect this shift in emphasis, the widget documentation for Uniface 10 has been restructured. It now documents the functionality, triggers, and properties of physical widgets, and describes logical widgets in terms of their purpose, since the functionality and properties can be changed by the developer.
To illustrate with an example:
By default, physical widget HTMLINPUT is mapped to EDITBOX, but HTMLINPUT can also be customized to get a custom Input search field which can set or return the value of the placeholder attribute.
Editbox = htmlinput(html:type=text;detail=dblclick)
Searchbox = htmlinput(html:type=text;html:size=20;html:placeholder="Type to search")
Above two configurations of same physical widget would result into two logical widgets with different capabilities:
If you are interested to know more about the widgets in Uniface, please visit the online documentation https://u.uniface.info/docs/1000/uniface/componentConstruction/widgets.htm?Highlight=widget
We have a great functionality available that makes it possible for you to follow a particular question or topic by turning on the “Watch” feature. It’s an easy way to stay informed about any issue that interests you. You will be notified by email when answers and comments are added to the question.
To watch a question
- Log in to https://www.uniface.info with your Uniface account details
- From the menu at the top, choose COMMUNITY, then choose Questions from the drop-down menu
- Choose the Question you're interested in to bring up its page
- Choose Watch on the right hand side to start receiving notifications, as shown below
You can also Watch a whole topic – then you’ll be notified whenever a question is added.
To watch a topic
- Log in to https://www.uniface.info with your Uniface account details
- From the menu at the top, choose COMMUNITY, then choose Topics from the drop-down menu
- Choose Watch under any topics you wish to be notified about
Should you wish to stop Watching any question or topic, go to your notification email and select one of the two questions given:
'Stop watching this question' or 'Unsubscribe from all notifications'
Follow using RSS
You can also follow new questions or particular topics using RSS. Watch out for the RSS link in the Questions list.
Blog by Peter Lammersma
What I like and expect in every well-designed system is predictability. Can I find what I am searching for in the expected location? In other words, is the interface intuitive and consistent?
That’s one of the best things about Uniface 10. Having worked with several earlier versions of Uniface, I can confidently say that this latest version’s user interface gives the developer unprecedented levels of consistency, predictability and effectiveness.
Overview of the Uniface 10 IDE
At a high level the IDE can be split into three main sections.
Figure 1 IDE main sections
As shown in Figure 1, these main sections are header, editors and message output. The last section, message output, contains the output of actions performed in the IDE. Pretty clear isn’t it? In this article I want to focus on the other two sections, because these are where the magic happens.
A Uniface developer works in the editors’ section. The IDE contains several editors. Let’s start by understanding these.
Main development objects and their editors
Uniface has introduced the term object in version 10. It’s a general term for the ‘things’ developers create and use, such as projects, components and fields. An object is a way for developers to communicate about their work without the need to bother with implementation details. In the article ‘About templates, models and objects’ I have described this concept in more detail.
Objects can be nested as children and parents. Some objects, such as fields, can only exist as children of other objects. Other objects, called main development objects, can exist without a parent and can have children of their own: examples include modeled entities, start-up shells, and projects
All main development objects have a dedicated editor in Uniface 10. When an object can only exist as a child of another object, that child must be maintained in an editor created for the parent.”. For instance, an entity painted on a component is the child of that component and must be maintained in the parent component’s editor.
It’s important to understand the difference between an entity created in the entity editor, which is called a modeled entity, and an entity that is painted on a component in the component editor, which is called a derived entity.
Uniface has a specific editor for every main development object. In the non-modal development environment, a developer can work on several objects in the same environment. Every open editor is identified by a tab.
Scope of your action
I started this article by talking about the predictability of the IDE. In the previous paragraphs I explained that Uniface has an editor for every main development object. The daily activities of the Uniface developer are actions such as creating new components, modifying properties of objects, writing script code, and compiling components. Some actions will be started from the IDE header, others in the editor section. To find the location of the action you want to do in the IDE, it’s good to consider the scope of your action.
- Does it do something to exactly one opened object? It will be in the editor of that object.
- Does your action involve more than one object, or is it not particularly related to an object in In short: The header contains global actions, while the editor contains actions relating to the content of the editor.
You can draw an imaginary line between the header and the editor section. Everything that relates to one particular object is somewhere below that line.
Let’s focus now on this editor section. "Although most editors have been rebuilt in Uniface 10, some of the less commonly used objects – for instance the maintenance of glyphs and keyboard translation tables – still use the U9 editors. As part of Uniface’s continuous delivery, these editors will be migrated to the new structure in the future. Every experienced Uniface developer will recognize the U9 versions immediately though.
Figure 2 The editor is a collection of worksheets
Every worksheet contains one or more tools. These tools depend on the editor and the worksheet. A typical worksheet composition has a resource browser on the left, the properties inspector on the right, and a large tool pane in the center. It’s in this tool pane the actual editing work is done. In this container the developer can, for instance, edit the script, define the key fields of an entity, or compose the structure of a service component. The general structure in the IDE is: editor à worksheet à tool.
Let’s take the editor shown in Figure 2 as an example. This is the modeled entity editor. The active worksheet is the Define Structure. This worksheet contains three tools. the left pane contains the ‘Resource Browser’, in the middle is the ‘Fields Composer’, and on the right is the ‘Properties Inspector.’
Zooming in on the worksheet tabs, I want to show you something interesting.
Figure 3 The worksheet tabs: my worksheets next to the Uniface defaults
In Figure 3, the Uniface default worksheets are shown and next to them are my own worksheets. In another article on ‘Enhancing the provided toolset’, I described how these worksheets can be added to your preferred Uniface editor(s), to make your work as a Uniface developer even more efficient. The worksheets offer great flexibility and power. In your own worksheet(s), you are not bound to the tool panes Uniface is using, and your actions have unlimited scope. You, the developer, are completely free to add a worksheet that performs actions outside the open object, though it is advisable to take the context of the object into consideration.
The IDE of Uniface 10 has the predictability I expect because it is a consistent implementation of the Uniface development paradigm. Uniface 10 is built by developers, for developers. It makes sense – common sense.
I can talk and write about the IDE for hours, but the best advice I can give is: just use it. I am convinced that you will, just like I do.
Blog by Frank Doodeman
There’s a handy feature in the Quick Search dialog of the IDE’s Code Editors: you can use regular expressions in your Search term.
This blog gives a few simple but useful examples.
Where is my variable assigned a value?
Suppose you have a variable or field named SUM, and you quickly want to find the places where some value is assigned to it by means of an assignment statement. In a ProcScript assignment statement, the variable being assigned to is always at the beginning of the line, and it is followed by a single equal sign followed by whatever value is being assigned to it. Therefore, use this regular expression to find all assignment statements that address variable SUM:
Let’s briefly go through the parts of this regular expression to see how it works:
- It starts with a caret sign: ^. This matches the start of a line.
- Then there’s \s*. The \s matches any blank character, such as space or tab, and the * specifies that it matches a sequence of zero or more of them.
- This is followed by the literal text sum, which matches the string “sum”. By the way, sum matches without taking case into consideration – behavior controlled by the match case button, which is off by default.
- Then there’s another \s*, matching a series of zero or more blank characters.
- It ends with a literal =, which matches an equal sign.
Where is my variable used?
To find where your variable SUM is used, use this regular expression as your Search term:
This specifies the literal text sum enclosed in \< and \> characters. The use of \< and \>, which match the start and end of a word respectively, ensures that the expression won’t find strings like SUMMARY, CHECKSUM or CONSUMPTION.
Remove trailing blanks from all lines
You can’t see trailing blanks, but they may still annoy you. With this simple regular expression, you can find them and replace them with nothing:
The \s we saw earlier: it matches any blank character. The + that follows it makes it match one or more of them. The $ stands for the end of the line. Use this regular expression as the Search term in the Quick Search dialog and empty the Replace term field in that dialog (make sure you set the dialog to Replace mode by pressing CTRL+H, or by clicking the down-arrow symbol on the left). Click the All button and voilà: no more trailing blanks in any of your lines.
Consistent use of the Struct arrow operator
You may have a coding convention for Struct member references that specifies that you use the -> operator without surrounding blanks, like this: vStruct->mbr. But suppose you stumble upon a piece of code from a former colleague who liked to have space characters around the arrow operator, like this: vStruct -> mbr. You can easily correct that using the Quick Search dialog and regular expressions. Your Search term should specify that you want to find the arrow operator enclosed in blanks:
Then by simply using -> as your Replace term you can replace all these space-consuming arrow operators by compact ones.
Use the new style of string substitution
In the old days, ProcScript string substitution was done using expressions such as "%%FIELD.ENT%%%", where the initial two percent signs indicate the start of the string substitution and the trailing three percent signs indicate its end. In Uniface 10 (and in recent Uniface 9 versions) you can do this in a better way: "%%(FIELD.ENT)". The double percent sign indicates the start of the substitution; the expression inside the parentheses is expanded and used as the result of the substitution. Not only is this easier on the eye, but it is also more flexible, as you can specify any expression between those parentheses.
Of course, if you encounter pieces of code that use the old-style string substitutions, you will want to replace them with new-style ones. Regular expressions come to the rescue:
The Search term starts with the double percent sign that indicates the start of a string substitution. The [^%"]+ means a series of one or more characters that are not percent signs or double quote characters. This part of the Search term is inside parentheses, because that makes it possible to refer to it in the Replace term – or more accurately, refer to whatever it matches. The regular expression ends with the three percent signs that indicate the end of an old-style string substitution.
The Replace term also starts with a double percent sign, since that is also the start of a new-style string substitution. Next comes an opening parenthesis. In the context of a Replace term, this is a literal character; it has no special meaning. The \1 indicates whatever is matched by the part inside the parentheses in the Search term. Then the Replace term ends, with the literal closing parenthesis.
Now, a single click on the All button replaces all old-style string substitutions with new-style substitutions.
Use special comment markers
In some of our Uniface projects, we use a special comment style – a semicolon followed by a dash – to write comments in our ProcScript code. We do this to distinguish real comments from code that was temporarily commented out by using plain semicolons.
If you encounter a piece of code that you know has real comments, but the programmer did not use the above convention, you can use the Quick Search box and regular expressions to correct this. Specify this as a Search term, to find comments that are not special style:
This regular expression consists of four parts:
- A caret sign: ^. This matches the start of a line.
- The first expression inside parentheses: ([^";]*). This matches any sequence of characters that are neither double quotes nor semicolons. It is enclosed in parentheses to make it possible to refer to it in the Replace term. The double quote is specified here because we don’t want to match lines that have semicolons inside hard-coded strings.
- A plain semicolon character: ;. This indicates the start of a ProcScript comment.
- The second expression inside parentheses: ([^\-]). This matches a single character that is not a dash. The dash needs to be escaped with a backslash character because, in a regular expression, a dash has special meaning if it is inside square brackets.
Then use this as the Replace term:
This specifies the first matched subexpression – the part of the line that precedes the semicolon; then a semicolon with a dash – the comment indicator that we want to use; and finally, the second matched subexpression, which is the first character that followed the semicolon.
Alert readers might realize that there may be lines with old-style comment that are not caught by the regular expression mentioned here. Which ones? That is left as an exercise for you: please post your answers in the comments section.
The IDE Code Editors are based on the Scintilla text editor, and therefore use Scintilla’s specific regular expression capabilities (in posix mode). On some points, this might slightly deviate from the regular expression syntax that you are used to. For more information, visit https://www.scintilla.org/SciTERegEx.html
Blog by Peter Lammersma
January, 25 2019
As an experienced software solutions creator (sounds prettier than ‘software developer’, doesn’t it?), I spend most of my time in Uniface’s Integrated Development Environment (IDE). The latest version 10 mentions template, model and object on nearly every editor. I think it’s important to know what they mean and to understand the difference between them. Spoiler alert: it has something to do with the level of abstraction.
Development objects, specialization and generalization
Let’s start with objects. I have been using Uniface to develop and deploy applications for many years and I know the ins and outs of Uniface, but I have never seen something that is called an object. In fact, an object is a generalized term for things you and I work with every day.
Anytime you read the word ‘object’, you can replace it with anything you know in Uniface, like field, entity, menu, property, component, etc. These specializations are implementations of objects and are categorized as development objects. Development objects are created and maintained in the IDE.
Some development objects have parents. For example, a field can never exist without an entity, and it’s impossible to define a menu without a library.
Development objects can also be nested. For instance, a component contains at least one entity, and an entity contains fields. To look at it the other way around, the fields have the entity as their parent and the entity has the component as its parent.
Development objects that don’t have a parent, like components and application shells, are called main development objects. Main development objects have a dedicated editor in the IDE.
In the Uniface world, it’s all about the level of abstraction. Templates and modeled objects help you create your development objects. Templates are used to create both objects and modeled objects. The biggest difference between a template and a modeled object is inheritance. This is shown in Figure 1.
Figure 1 Relationship between template, modeled object, and object
The template is the most abstract level, while an object is concrete.
Anything created from a template has no inheritance from that template. A change in the template does not affect the (modeled) object at all. The (modeled) object is a separate copy from the template.
Uniface delivers a set of templates you can work with, but you can also create your own. In the new Uniface 10 development environment, the first thing a developer does is create a repository that will be based on templates. The first time Uniface is started, the developer must specify and load a set of templates. This can be the default Uniface set or a tailormade set of templates. But once loaded in the repository, they are static: they are not development objects.
Modeled objects are a kind of template, but they are created and maintained in the current development repository. This means they add dynamics to the templates.
A modification made in a modeled object is inherited by an object based on that modeled object. This is the inheritance that we, Uniface developers, have known and used for many years.
Template or model
For us Uniface developers, it’s common practice to define a modeled representation of the structured data with entities and fields. As soon as these modeled entities and fields are ‘painted’ on a component, they become derived entities and fields. We know and trust that all properties and scripts are inherited from the model. That’s what makes Uniface so efficient. And that is why you and I use Uniface.
Let’s picture the template, model and object as layers and forget about the specialization of the objects for a minute.
Figure 2 Template, model and object as layers
As shown in the figure, every object is a copy of a template. The model layer adds inheritance, but this is optional.
Every part of your development object is in fact based on templates. Every component, entity, field, etc. is a copy of a template. If you want to save development time or enhance maintainability, you can add inheritance to properties or coding by adding a modeled object layer for these objects.
From modeled to derived objects
Here’s a small example to illustrate what I’ve just been discussing. An application has a few components and a couple of database tables with fields. From a business perspective, the data is the most important element; the application is there to serve the data. To ensure the consistency of the data, it’s normal for us, as Uniface developers, to define modeled entities. These modeled entities have fields, keys and relationships; all of these are modeled too. This model allows the developer to use the data on components without the need to know anything about the implementation of the database.
This is a major strength of Uniface. Again, as soon as a modeled entity is used on a component it is a derived entity and used fields are derived fields.
In case of the modeled entities and fields, every Uniface developer uses templates and models daily. Uniface 10 has enhanced the use of models through the whole environment. It’s up to the developer to use this concept. Templates and modeled objects are present at nearly every stage of the development process, and they make the lives of developers easier and more efficient.
Using modeled objects as much as possible is a logical move. When you want to take a model-driven approach to Uniface application development, using models is a must!
Blog by Gerton Leijdekker
February, 7 2019
In Uniface 10, developers can open development objects from, among other places, the U-Bar by entering the object's full name or selecting the desired object from a list. For small applications these are very useful options however, for larger applications, having a simple way of searching for objects would improve the user's experience and reduce the frustration of searching through, what could possibly be, a long list.
To improve the user experience and provide a simple way to search for objects, we have added smart suggestions to the main U-Bar.
Smart suggestions are intended to help enter a value that is relevant in a given context, such as the URL of an object, the value of a property, code, or a new name of an object. They can help with entering correct syntax, as well as with finding objects while entering a URL.
Suggestions are offered as you type. Simply start typing, and based on what you enter, suggestions are offered in a drop-down box below the field. You can quickly accept a suggestion using the down/up keys, then continue to enter more text, or press Enter/Tab to select the value.
The offered suggestions depend on the purpose of the entry field and what you type.
Suggestions in the Main U-Bar
The purpose of the Main U-Bar is to open an object for editing. Object URLs have a defined syntax, so the suggestions offered depend on how much of the URL you have entered or selected.
To start with, you need to enter the code of the main development object. If you don’t know the type code, try a keyword, such as form, service, entity, or include to get suggestions based on the description.
If you do know the code, you can just start typing it, for example cpt for components. In this case, a list of component types is offered.
Use the navigation keys to select the type of object you are looking for and press Enter to select it.
(Of course, the list of available types is small, so the easiest way is just to select the type from the list of suggestions without typing anything. 😊)
Suggestions for Objects
Once you have selected the main object type, you can start typing the name of the object, or a string that occurs in the object name or description. While typing, suggestions are offered. The first item that matches is highlighted.
If there is no exact match, suggestions are provided for items that contain the string somewhere in the name or description.
Depending on your naming conventions, your object names and/or descriptions may contain keywords that represent some functional domain, sub-application, or some sort of category. Such information can be used in the U-Bar to find your objects.
Use the arrow keys to accept a suggestion, and press Enter or Tab to open it. However, if you want to open the object at a specific sub-object, type a forward slash to get the next object type suggestions.
You can then select the sub-object type to get the next suggestions.
If your naming conventions are a bit more complex, you can use wildcards * and ? or Uniface characters profile (Gold+*, Gold+?) to enter a naming pattern. For example, perhaps you have a naming convention for components that uses the first 2 characters to specify a functional domain, followed by 4, followed by 2 characters to specify some functional behavior (browse, maintenance, edit, open, erase, batch, …). You could then enter a string like AU????BR, or *BR to find the matching components.
What is considered smart depends on the context. The suggestions at the top of the list are considered most relevant; probably the thing you’re looking for. Does the IDE really know? No, but it does make an educated guess.
In the Main U-Bar, for each object type, suggestions are ordered based on modification date, because you often look for an object you recently worked on.
Once you start entering something after the object type, the suggestions are offered in the following order:
- Objects whose name starts with the entered text
- Objects whose name contains the entered text
- Objects whose description contains the entered text
By default, the number of suggestions offered is limited to 50, which allows the IDE to show suggestions instantly. Depending on the connection speed between the IDE and your Repository, you may want to tweak this number by using an assignment file setting. In practice, if your object is not in the first 50, you will probably make your search criteria more specific.
There are situations where you simply don’t know what you’re looking for—you just want to explore the Repository a bit. For such situations, you can have the IDE show all suggestions, allowing you to scroll through the list of suggested objects using the scrollbar.
We feel this is a really useful feature that helps developers navigate around their application’s sources using Uniface 10.
Blog: Peter Lammersma
Enhancing the provided toolset
The new Uniface 10 IDE (Integrated Development Environment) offers a well-equipped toolbox It provides nearly everything a developer needs to build and maintain software applications. But sometimes you want a bit more or need to add a personal touch to the tools provided.
Every developer uses several tools and utilities to do his/her Uniface work effectively.
These are the ones I can’t do without:
- Uniface 10 to build web and mobile applications.
- Notepad++ is the editor for all files I don’t edit with Uniface. It is based on the powerful Scintilla editor.
- To monitor all communications to and from other applications I use Wireshark. This is also perfect for monitoring network traffic.
- In addition to Wireshark I use a very old tool called Nettool. This tool is easy to use and perfect for creating an http tunnel.
- To monitor processes on my computer, Sysinternals Process Explorer is indispensable. The developer of this tool, Mark Russinovich, has created a lot of nice tools. If you don’t know about these, just check them out!
- A database management tool – the choice depends on the database being used. During development I use SQLite studio, since the repository is stored in a SQLite database.
- GIT and Sourcetree to interface between my local environment and Gitlab. A modern developer can’t do without version control.
Most of the time, my work is done in the Uniface IDE. Adding extra utilities was and is very useful. Like most developers, I build my own Uniface utilities. These utilities are components built in Uniface that let you perform actions in the IDE.
The functionality of the utilities I use today is very close to what I have been using for the past few years. In previous versions of Uniface, the additional menu was the place to store additional functionality. Uniface 10 offers two places: User Defined Menus and User Defined Worksheets. The first adds a menu entry in the action or global menu, while the second adds a worksheet to one of the editors.
Using the User Defined Menus or Worksheets is very easy, and powerful at the same time. To use the additional tools I already had in the User Defined Worksheets – the solution I like most – only a few changes were needed, and then I was able to utilise the enhanced functionality Uniface 10 offers. This one-time change is really easy and certainly worthwhile. Your own tools can be integrated into Uniface 10 seamlessly.
I’ll now describe two tools I built a couple of years ago and use now in Uniface 10.
My version control interface
The utility I use every day is a basic version control interface. It consists of a Uniface form to create an export of the object I am working on. With the User Defined Worksheets solution, this form has become an integral part of my IDE. The form with the additional functionality is now (with Uniface 10) a tab in the editor of the object.
Before starting a modification to an object – a component for instance – I open this worksheet and it checks if I have the latest version of the object I am about to change. After my work is done, I open this worksheet again to save the latest version of the object to a file on my computer. The User Defined Worksheet has a default operation, ws_refresh, that is fired when the object is changed. This local copy is created by the $UDE function of Uniface. With the external tools GIT and SourceTree, local versions of the objects are stored in Gitlab.
I have made this additional tool available on every editor in the IDE. Version control is important regardless of the type of component.
My entity utility
Another tool I use adds value in the entity editor. The flexibility of the User Defined Worksheet solution in Uniface 10 allows me to add tooling to specific editors in the IDE. This entity utility provides additional information and actions in the entity editor of the IDE.
It adds a new tab to the IDE to show me where the entity, which is opened in the editor, is used, and allows me to perform actions on that particular entity. Besides an overview of all the relationships this entity has, it shows all the components on which the entity (or a subtype of it) is used. It offers functionality to open related entities and components. It also compiles all related components.
Figure 1 An example of my Entity Utilities worksheet
Information about the Uniface repository can be read in the meta dictionary – nothing new about that. What is new in Uniface10 is that information about the current object (as opened in the current instance of the Uniface editor) is available in the U-Bar. The value of the U-Bar is a parameter of the default operation ws_activate. Opening a component in the corresponding editor can be achieved by calling the operation navigateTo in the IDE APIcomponent IDE_API_1.
Wrapping it up
Uniface makes it very easy to add functionality to the IDE. It is enough to have a Uniface resources file and a logical path in the assignment file to enhance the IDE. Use it to add your own tools or to utilise those of others. That last option is very interesting 😊. I wonder what tools you have created and use?
This is still something I would really love to see added to Uniface: a library to share sources, frameworks, samples, tools and other add-ons. It could even be an add-on to the IDE itself.
On Uniface.info there is already a section called ‘Uniface utilities, add ons and extras’. If you have any Uniface 10 additional tooling you want to share, please send it to firstname.lastname@example.org and the Uniface Support team will be happy to add it. I look forward your input!”
(Original creator: Gerton)
DSP JS API function:
Putting application developers in control of the presentation layer
HTML5 already provides a powerful set of form controls out of the box, and its functionality is continuing to grow and mature. To get access to all that functionality, application developers need to be able to interface directly with the controls. Uniface 10.3 Dynamic Server Pages provides exactly that capability.
Before we go into detail, let’s see how Uniface’s support for web technology has evolved over time to give developers more and more control over their applications.
The beginning: Uniface Server Pages
Uniface 7.2 provided our first functionality for the web: The Static Server Page, also known as the Uniface Server Page (USP). USPs enable binding between the Uniface server-side data structure and an HTML client side. They handle communication between client and server in a very simple way: the server generates an HTML page complete with data substituted into the HTML, and the browser simply displays that HTML page. Updates are initiated by the browser via a standard HTML submit, after which the server will load the updates and reconnect them with the back end. After that, the server again generates a full-page response with all changes handled, and the whole process starts again from the beginning.
A leap forward: Dynamic Server Pages
Uniface 9.4 introduced the Dynamic Server Page (DSP) allowing Uniface developers to create rich internet applications (RIAs). The biggest difference between a USP and a DSP is the absence of full-page refreshes in the DSP. Obviously, data is still sent to the server and received back by the client, but instead of the whole page being refreshed, only the affected data is returned and merged into the page displayed in the browser. All communication is handled by the Uniface DSP and programming is as easy as writing some ProcScript in a trigger. In addition, Uniface 9.4 DSPs provide out-of-the-box client-side syntax checking, which, in case of a syntax error, avoids a round trip to the server. A DSP consists of a server part and a client part. The client part has a copy of the component definition, which is what allows the client to perform syntax checking.
Introducing the ability to manipulate client data
Application developers take charge of the presentation layer
With Uniface 10.3, we have now also opened up the presentation layer of the client: the Document Object Model (DOM) layer. Using a simple function, a Uniface data object can now get a reference to its bound element in the DOM layer, allowing Uniface developers to access DOM elements in the context of that field, its occurrences, and its instance. The function is:
uniface.field.getBoundElement(ViewId) From the bound DOM element, it is possible to navigate to sibling and parent elements. In case of an AttributesOnly field, the same technique can be used to navigate to child elements. This gives Uniface developers full control of the DOM, allowing integration of third-party JS libraries that integrate at DOM level.
In the following code example we will use the new JS function to change the default reporting of client side syntax errors. The webtrigger onSyntaxError is the trigger that gets fired the moment the client encounters a syntax error. The default way for Uniface to respond in this situation is to set an error class on the element bound to the field that is in error. CSS would then style it appropriately. The code below overwrites the default behavior and sets the error class to the parent element of the element bound to the field:
The getBouldElement() function is simple to use and provides full access to the DOM layer of the browser. It opens up communication with any JS technology that needs to interface on the presentation layer.
Blog by Jason Huggins
The latest releases of Uniface 9 and 10 mark a significant milestone in the enhancement of security, both under the covers along with new functionality to secure applications.
I believe that in practice all organizations need to protect aspects of business confidentially, competitive edge, adhere to applicable privacy regulations and prevent data theft/manipulation. Protecting data is paramount for practically everyone. It can feel like the wild west at times, with attacks coming from all directions, for example an employee, a contractor/visitor, a cyber-criminal, malware/ransomware, accidental hackers, curious observers… the list goes on! Whether the data breach is internal, external, malicious or accidental, the risk sheould be understood, assessed and addressed. The statistics of count, size and cost to a victim show that global data breaches have been on a continual increase each year. The current average cost of breaches is in the millions of dollars range, with total costs per year globally in the billions. Breach sizes have ranged from tens of millions of confidential records up to many billions of lines of data. Predictions suggest that a clear majority of enterprise traffic will be encrypted throughout 2019. It is important for Uniface to support this, whilst making it an easy as part of the development and deployment platform to utilize.
What is the threat?
There are many threats to data security for which network security exposes a key flaw. There is an inherent weakness in the standard TCP/IP network model and IPv4 because none of the layers include security features as such. The protocols ensure very reliable transmission of data however do not fully ensure data integrity or confidentially. It is extremely easy to sniff and tamper with the data in real time. But wait, what about IPv6 you may ask? Well IPsec, a security protocol, is built into the IPv6 standard however it is not mandatory. The official launch of IPv6 was in 2012 however IPv4 is still the dominant protocol covering around 75% of deployments. The rate of adoption appears to be slowing however this does not in any way mean that IPv6 will not become the dominant standard, it may just take a little longer than expected. IPSec within IPv6 will not necessarily become the drop-in solution to the security hole. It is still valid to apply alternative or additional mechanisms to secure the transmitted data. The Uniface implementation means that the application can with ease, reliably ensure encryption is applied whatever the underlying IPv’N’ network infrastructure implementation and protocol support may be.
What’s new in network security?
Uniface now has a cryptography layer added to its network stack. The implementation is a TLS layer built on top of the standard TCP driver. The TCP driver itself has been refactored yielding several improvements. The new TLS driver utilises OpenSSL libraries. OpenSSL, often referred to as the
‘Swiss Army Knife’ of cryptography, is well maintained/supported, has excellent platform coverage and is backed by major organizations. It implements both Pre-shared key (PSK) and Asymmetric Certificate/Key pair verification, the later providing greater levels of security. The cryptography methods supported, called ciphers, are those of OpenSSL, however by default Uniface will only list the stronger ciphers. The new driver encrypts the network traffic, including IPv6, between Uniface processes encompassing both shared and exclusive servers. A key feature supported by the TLS driver is ‘Peer Name Verification’, which helps mitigate compromises such as ‘Man in the Middle’ attacks. Configuration is very straight forward matching the typical driver approach, with familiar mnemonics such as ‘tls:’ & ‘USYS$TLS_PARAMS’.
The configuration and various possibilities are well documented in the help.
Security is a shared responsibility spanning development and operations. Being more of configuration exercise, developers will see little change. The extra processing needed to encrypt/decrypt may have an influence e.g. transaction size and client vs server processing could become a consideration. Note: Uniface benchmarks match the published OpenSSL results. Operations should understand security, TLS and encryption, ensuring to pick ciphers that adhere to internal policies whilst maximising performance. The ‘pathscrambler’ is essential and must be used to safeguard the TLS configuration settings.
The TLS driver is simple to use and should be considered an essential priority for most.