Quit storing your applications' property values in data areas, and make your programs easier to understand.
One of the programming practices I've never cared for is the use of data areas to store property values for an application. While a data area is a useful tool for the programmer who designed the system, it isn't user-friendly for those of us who need to work on it later. Usually, the data area contains a random mass of data strung together in an incoherent fashion, and without good documentation it is difficult to determine what the data is used for. Consider the example data area in Figure 1. Why is there a "Y" in position 40? What's it used for? Is the number that starts in position 33 a 7-digit number, or is it a 4-digit number followed by a 3-digit number? Again, without some sort of external documentation of the data area, it's impossible to tell just by looking at the contents of the data area what the data is being used for.
Data area . . . . . . . : PRODTEST
Library . . . . . . . : CGIBIN
Type . . . . . . . . . : *CHAR
Length . . . . . . . . : 250
Text . . . . . . . . . : Example Data Area
Value
Offset *...+....1....+....2....+....3....+....4....+....5
0 'My Property value Juarez, MX 0000018YNYYYN03302'
Figure 1: Example Data Area PRODTEST
In addition, if maintenance of the data area is required, either the IT department will have to update it using the CHGDTAARA command or a custom display will need to be developed along with a corresponding program to update the data.
Java properties files, on the other hand, carry none of these burdens. A properties file is simply a plain-text file that can be created in Notepad (or a similar text editor) and then saved to the IFS with a .properties extension. Because they can be viewed or edited with any text editor, there is no need to do any special programming in order to maintain them. Also, because properties files can contain comments, the purpose of the values in the file can be clearly documented. Additionally, since data is stored in the format of key name equals key value, it's a lot easier to determine what the data is being used for because the key names can be as descriptive as you want them to be.
In order to use properties files from iSeries applications, I chose to create a prototype called RetrieveDataFromPropFile and store it in a service program called IFS_TOOLS. The prototype takes two pieces of data as input: the name and path to the properties file and the key value to retrieve. The prototype returns either the value of the key or blanks if the key wasn't found. The prototype will also return blanks if the properties file isn't found.
H Option(*NoDebugIO:*SrcStmt)
H Thread(*Serialize) NoMain
/copy Source,IFS_ToolsC
/copy QSYSINC/QRPGLESRC,JNI
*<doc>*************************************************** @Program
* RetrieveDataFromPropFile
* @Description
* Retrieve Data From Properties File
* @Parameters
* PropFileVal - The Name Of The Properties File
* @Parameters
* PropFileVal - The Name Of The Properties File
* KeyVal - The Key Value To Retrieve
* @Returns
* Value Assigned To This Key
****************************************************</doc>
P RetrieveDataFromPropFile...
P b export
D RetrieveDataFromPropFile...
D pi 5000A
D PropFileVal 1024A Const Varying
D KeyVal 1024A Const Varying
D PropConfig S like(PropertiesConfiguration)
D PropFile S 100A
D PropFileStr S like(jString)
D PropString S like(jString)
/free
Monitor;
PropFileStr = new_String(%Trim(PropFileVal));
If PropConfig = *Null;
PropConfig = new_propertiesConfiguartion(PropFileStr);
EndIf;
PropString = PropertiesConfiguartion_getString(PropConfig :
new_String(%Trim(KeyVal)));
return Convert_String_To_Alpha(PropString);
On-Error;
return *Blanks;
EndMon;
/end-free
P e
P Convert_String_To_Alpha...
P B Export
D Convert_String_To_Alpha...
D PI 1024A
D String like(jString)
D String_Long S 10I 0
D Text S 1024A
/Free
String_Long = String_length(String);
String_getBytes(String : 0 : String_Long :
Text : 0);
Return Text;
/End-Free
P E
Figure 2: Source Listing for IFS_TOOLS Service Program
As you can see, the code to access a properties file is quite simple. The prototype simply creates a properties file object using a Java constructor and then uses the getString method to retrieve the desired key value. Since the result is returned as a Java string object, it should be converted into a format that is meaningful to an RPG programmer. The conversion is performed using the getBytes method of the Java String class in the Convert_String_To_Alpha prototype. This converts the Java string into an RPG character string.
The necessary Java objects have been prototyped in a separate copy file (see Figure 3) in order to promote code reuse. Because the PropertiesConfiguration Java class is not native to the iSeries, several jar files will need to be installed on your system from the Apache Commons project in order for the code to be enabled for execution. (I will explain what jars are needed and where to get them later.) Although this article uses only a single class (PropertiesConfiguration) and a single method (getString) from the configuration package, the Apache Commons collection contains a multitude of other Java classes that can be accessed from the iSeries as well. Some of the more commonly used components include Digester (used to manipulate XML), Logging, and FileUpload. Considering the ease with which these classes can be integrated into RPG applications, it's well worth the effort to check them out.
D new_String PR like(jString)
D EXTPROC(*JAVA
D :'java.lang.String'
D :*CONSTRUCTOR)
D create_from 1024A VARYING const
D String_length...
D PR 10I 0
D EXTPROC(*JAVA
D :'java.lang.String'
D :'length')
D String_getBytes...
D PR EXTPROC(*JAVA
D :'java.lang.String'
D :'getBytes')
D SrcBegin 10I 0 Value
D SrcEnd 10I 0 Value
D Dest 1024A
D DestBegin 10I 0 Value
D PropertiesConfiguration...
D S O CLASS(*JAVA
D :'org.apache.commons.-
D configuration.-
D PropertiesConfiguration')
D new_propertiesConfiguartion...
D PR like(PropertiesConfiguration)
D EXTPROC(*JAVA
D :'org.apache.commons.-
D configuration.-
D PropertiesConfiguration'
D :*CONSTRUCTOR)
D PropFileName like(jString)
D PropertiesConfiguartion_getString...
D PR like(jString)
D EXTPROC(*JAVA
D :'org.apache.commons.-
D configuration.-
D PropertiesConfiguration'
D :'getString')
D KeyValue like(jString) Const
D RetrieveDataFromPropFile...
D pr 5000A
D PropFileVal 1024A Const Varying
D KeyVal 1024A Const Varying
D Convert_String_To_Alpha...
D PR 1024A
D String like(jString)
Figure 3: Source Listing for IFS_ToolsC Copy Member
To create the service program, use the following commands:
CRTRPGMOD MODULE(MyLib/IFS_TOOLS)
CRTSRVPGM SRVPGM(MyLib/IFS_TOOLS) MODULE(MyLib/IFS_TOOLS)
SRCFILE(MyLib/SOURCE) SRCMBR(IFS_TOOLSB)
When creating service programs, I always create a separate binding source file to make it easier to change the service program later if I need to. If you don't have a great deal of experience with service programs, you may think this is an unnecessary waste of time, but trust me; it isn't. Using binding source will save you many headaches down the road.
STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('IFS_TOOLS v1.01')
EXPORT SYMBOL("RETRIEVEDATAFROMPROPFILE")
EXPORT SYMBOL("CONVERT_STRING_TO_ALPHA")
ENDPGMEXP
Figure 4: Binding source member IFS_TOOLSB
Now that you've created the service program, the next step is to create a properties file and save it to a directory in the IFS.
# Comments start with the # sign
# This properties file is used for...
# Sample property PROP_ID_1
PROP_ID_1=My property value
# Text values that contain commas (,) must be escaped with a # backslash ()
# Properties can have multiple values separated by commas. I did not
# implement this functionality so only one value will be returned.
# If commas are not escaped the prototype will return everything until
# the first comma is encountered.
# System Identifier Text
SYSTEM_ID_TXT=Juarez, MX
# Initial system selected in drop-down box
SYSTEM_ID_SELECTED=Juarez
# Number of items in drop-down box
SYSTEM_ID_NUM=18
#Note: Numeric values are returned as text and must be converted
Figure 5: Sample Properties File /mydir/test.properties
In order to access the properties file using the new service program IFS_TOOLS, use the sample program in Figure 6.
D PropFile S 1024A
D SystemID S 100A
/Copy Source,IFS_ToolsC
PropFile = ‘/mydir/test.properties';
SystemID = RetrieveDataFromPropFile(PropFile :
‘SYSTEM_ID_TXT');
*InLr = *On;
// SystemID will equal Juarez, MX
Figure 6: Sample RPG Program PROPTEST for Retrieving a Property from a Properties File
To create the sample program, use the following commands:
CRTRPGMOD MODULE(MyLib/PROPTEST)
CRTPGM PGM(MyLib/PROPTEST) BNDSRVPGM(MyLib/IFS_TOOLS)
Before running the sample program, you must install the required jar files:
- Commons-configuration-1.1.jar
- Commons-collections-3.1.jar
- Commons-lang-2.0.jar
- Commons-logging.jar
These can be easily found online by doing a quick Google search for Apache Commons or by navigating to http://commons.apache.org/. The easiest way to install them on your iSeries after you have downloaded them is to simply save them to the folder /QIBM/UserData/Java400/ext. Any jar files stored in this folder will automatically be found when the JVM starts, so there is no need to add them to your classpath. If you save them to any other IFS folder, you will need to explicitly add them to your classpath using the ADDENVVAR command before running the sample program.
While the code to implement the use of properties files is simple, the concept is powerful. One of the best uses I have found for properties files is multiple language support. I create a properties file and then enter values for everything that will be displayed on Web pages, displayed on reports, etc. Once I have the English version complete, I send it off to be translated into Spanish, Chinese, etc. By using the prototype described in this article, switching from one language to another is a breeze. I simply pull the properties from whichever language file is required per the user's request.
In summary, using a Java properties file is a great way to make an application more user-friendly because the properties can easily be updated, documented, and shared by many applications on a wide variety of platforms. By utilizing properties files, you can be assured that whatever application needs the data can access the data using only pure Java methods, thus eliminating the need to store the properties on multiple systems. Since the properties files can be (and should be) well-documented, developers no longer have to waste time figuring out what the data means before getting to work on fixing problems. These factors make replacing data areas with properties files a sound business decision and one that is well worth the investment.
LATEST COMMENTS
MC Press Online