TechTip: Replace Data Areas with Java Properties Files

General
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

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.

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$0.00 Raised:
$