In this chapter deals with the content of the shared plugin of any Scout application. As the name ”shared already indicates, this plugin contains code and resources that need to be available to both the Scout client and the server application.
The chapter starts with the internationalization of texts in Scout and icon resources. Then, the less visible components are introduced. These include permissions, code types, lookup calls and form data objects.
Code types and codes are widely used in business applications. In general, any fixed set of named entities can be seen as a code type. Code types can be used to model the organisational structure of companies, to represent business units or to categorise or segment entities. Frequently, enumerations or enumerated types1 are used as synonyms for code types. The individual named entities in a code type are called codes in Scout.
Both code types and codes have associated names (translated texts) and IDs. As in the case of standard Java enumerations, Scout codes can also have associated values. A set of additional features enhances Scout code types over simple Java enumerations:
The text below first introduces the basic features of code types and codes using a simple example with static codes. Then, hierarchical code types and the dynamic loading of codes from external sources is explained.
As a simple example we assume that an event managing organization works with an application to plan events for customers. To distinguish public and private events it is natural to define a corresponding code type. Both the code type and all its elements will have an assigned ID and associated translated texts. See Listing 4.1 for a possible implementation of such a code type.
The code type class and its codes shown in Listing 4.1 have been created using the creation wizards provided by the Scout SDK as described in Section ??. In Scout, code type classes are derived from class AbstractCodeType<CODE_TYPE_ID, CODE_ID>. In the provided example, both the code type ID and the code ID are typed with Long. The value of the event code type ID is assigned by Long ID = 10000L. The contained codes for public and private events are realized by the inner classes PublicCode and PrivateCode that are derived from Scout’s AbstractCode<CODE_ID> class. Their individual IDs then have assigned the numbers 10010 and 10020 respectively. This pattern follows the convention to leave an ample number space between any two code type IDs. This space can then be used for the individual codes of a code type that need ID values as well.
In the above example the types for the ID values are defined by the generic parameter <Long>. And other classes from the package java.lang work well too. In fact, any Java class may be used as a key type for code types and codes as long as it satisfies the following requirements:
To allow for language specific translations, the configuration method getConfiguredText is used for both the names of code types and codes. A frequently used code property is the active flag to mark obsolete codes. Setting individual codes to inactive is useful for codes that are still linked with existing data but should not longer be used when entering new data into the application. As shown in Listing 4.2, codes can be marked inactive by returning false in method getConfiguredActive.
A set of additional code properties is available to control the appearance of individual codes. Clicking on an individual code in the Scout Explorer provides the list in the Scout Object Property view.
To explain the definition and use of hierarchical codes we use the Industry Classification Benchmark as a concrete example. The Industry Classification Benchmark or ICB2 allows to hierarchically classify companies and organisations into industries, super sectors, sectors and sub sectors. Each organizational level has a unique number assigned and a name. This setup can easily be transferred to a hierarchical Scout code type.
The corresponding code for the ICB code type is provided in Listing 4.3 where its hierarchical nature is reflected by method getConfiguredIsHierarchy. The actual hierarchical codes are then implemented as nested inner code classes that are derived from Scout class AbstractCode. See Figure 4.1 for a screenshot of the partially expanded ICB code type class in the Scout SDK.
Although codes types remain mostly static in their nature, they do evolve over time in any real world application. Requiring that all codes are statically defined in the application’s code base would result in the necessity to update the code base for every change of a code required by the business. Clearly, such a setup is not sustainable and this is why Scout allows to dynamically update the set of codes contained in a code type.
At startup of a Scout application the codes of all defined code types are loaded into memory. For this, Scout internally calls method loadCodes for each code type class derived from class AbstractCodeType. In this method Scout first creates objects representing the statically defined codes and then dynamically adds additional codes in method execLoadCodes. By overriding this method, a code type class can dynamically add codes from any external sources. An example for the dynamic loading of codes is provided in Listing 4.4. Please note that this code snipped only illustrates the principle and does therefore not access any external web services or databases.
As codes have IDs and can be defined both statically in code and dynamically from external data, conflicting definitions of codes are inevitable. In the Scout framework these conflicts are resolved in method execOverrideCode. In the default implementation provided by class AbstractCodeType, priority is given to the dynamically defined code. Only attributes that are undefined for the dynamic code are copied from the static code definition. This logic can be changed for any code type by simply overriding method execOverrideCode with the desired behaviour. In the example provided in Listing 4.4 the code with ID Color.YELLOW is defined both statically and dynamically. As a result, the translated text for key "YellowDynamic" is shown in the user interface as it has priority over the statically defined text key "Yellow".
To have access to all codes at runtime, Scout provides the convenience accessor CODES. This accessor encapsulates the access to the ICodeService and provides a number of useful methods. At startup, all codes are loaded and cached in the applications client session using method getAllCodeTypes. And for a class MyCodeType, all its codes can be retrieved by CODES.getCodeType(MyCodeType.class).getCodes().
Lookup calls are are used to look up lists of lookup rows in the form of key-text pairs. The list of lookup rows returned is usually defined by some search criteria. When the look up is triggered by a key, only a single element is returned. And when a string is provided as a search criteria, the returned list typically contains the lookup rows that contain the given search text as a substring.
For lookup calls two main use cases exist. In the first case, the lookup data is locally available, not too large and can be kept in memory. In this situation, the lookup data can be directly created in the call itself. As an example, you may consider a lookup call where the lookup data is based on a code type. In the other case, the lookup data is dynamic in nature, the amount of data is large and needs to be read from some external source, such as a database or a web service. To access large amounts of external data, a lookup call typically invokes a so called lookup service that is providing the necessary data. This is exactly the scenario that was used in the ”My Contacts application of the book’s first part in Section ??. In the contact form of that application, a company smart field is used to let the user select a specific entry from a list of companies. And in turn, this smart field uses a company lookup call that is backed by a company lookup service. This lookup service then accesses a database to create the list of companies required for the company smart field.
in the text below (0) general aspects: * getDataByKey—Text—Rec?—All * additional properties as constraints to the result set: master field * for a specific implementation additional properties can be added with getters/setters ? -¿ yes as they are passed to services as bind variables (1) local lookup calls in the client plugin (2) lookup calls in the shared plugin (3) lookup services are only mentioned here for completeness. full discussion in book part 3 for scout server? or not? probably needs to be here ...
TODO: fix Figure 4.2: MyLookupService extends AbstractLookupService and implements IMyLookupService that extends ILookupService which
* lookup service * sqllookup service
needs text, topic is relevant for client, server, and security. what to present where to be decided
needs text, explain that form data objects are data transfer objects
needs text, this is about Form Data Export and Import