Home ยป Application Modernization ยป RPG Programming Language: All you Need to Know

RPG Programming Language: All you Need to Know

Published On September 6, 2022

Pain-free Software
Modernization

Keep the light on.

Join our mailing list for development guides and solutions for constant IT innovation.


If you have worked on IBM i application development, you must have heard about RPG programming language. Developers use it on a IBM system โ€“ the AS400 or iSeries. But what is RPG? What is it used for? Should you start learning it? In this article, you will find all the details.

What does RPG stand for?

RPG stands for Report Programming Generator. It refers to a high-level programming language that includes a series of procedural steps to complete. RPG was developed by IBM in the year 1959. It still works as the primary programming language for IBM computers.

The meaning of RPG has gone through several changes since its inception throughout these years. Early versions of RPG ran on the old AS400 and iSeries machines as the primary programming language. The latest version is known as RPG IV. It is used for commercial business application development on IBM’s minicomputer system.

Who uses the RPG language?

Software developers and programmers use RPG. It enables you to create, update, and maintain business applications on IBM computer systems. Developers use it for a variety of purposes. For example, users can utilize RPG to automate business workflow.

Why should developers learn RPG?

There are plenty of reasons for learning RPG programming, including widespread use and in-demand skill. Letโ€™s find them out.

Are businesses still using RPG programming language?

IBM i is still considered one of the leading enterprise platforms. Small and large business users rely on it to power critical operations. The majority of these companies are still using multiple RPG-based applications. The apps need maintenance, updates, and modernization. Hence, developers should learn RPG programming, as businesses are still using it to power their operations.

Does the market lack RPG developers with high skills?

Thousands of businesses are using RPG programming language for their apps. However, there is a shortage of skilled developers. From 2017 to 2020, around 33% of active RPG and COBOL developers went to retirement. Also, the new generation of programmers are not interested in โ€œlegacyโ€ languages like RPG. Developers are more interested in investing time and effort in modern programming languages. Hence, the talent pool is continuously shrinking. Developers can turn this situation into a great opportunity. By learning RPG, you can enter into a space that has high demand but less competition. As a result, you have a higher chance of landing highly paid jobs.

Can integrating the programs with modern technologies be time-consuming?

If you want to use RPG programs, you have to integrate them with the latest tools and technologies. Otherwise, it will be impossible to meet the business demands. However, integrating the RPG programs with modern technologies and tools can be very difficult for developers. It can take a lot of time.

To solve this common issue, you can use modern low-code tools. They enable you to modernize RPG business apps without migration. As a result, they have become massively popular. For example, developers can utilize Visual LANSA to simplify the modernization of legacy tools. It has the ability to make application development workflow up to ten times faster. Hence, you can quickly modernize your legacy app.

Read: Why You Should Modernize Your RPG and COBOL 5250 Apps

What is RPG programming language used for?

Developers use RPG language for commercial business application development on IBMโ€™s leading minicomputer system โ€“ the AS400 or iSeries. It provides users with an interactive programming environment. Hence, you can conveniently enhance existing software applications or automate the existing business processes.

How can I connect my RPG programs with modern web and mobile applications with LANSA?

Developers can connect RPG programs with apps by using LANSA integrator. It is based on the Java Service Framework. It enables easy integration between Java programs and RPG applications.

LANSA integrator supports a wide range of B2B technologies such as FTP, FTPS, SFTP, HTTP, HTTPS, SMTP, POP3, SOAP, and JMS. They eliminate complexities and simplify the integration process. Hence, you can save time and focus more on the business requirements.

Letโ€™s take a look at one of the practical examples of using LANSA integrator.

ExcelService Example

Let’s take a look at some source code of an ExcelService example built in RPG and after that we will take a look at the same example built in LANSA’s RDMLX. The RDMLX version is much shorter than the RPG version.

What does the example look like in RPG?

Refer to shipped RPG source file QRPGLRSRC and CRTDEMO program source in QCLSRC source file.

This example is self contained and requires no additional work besides compilation.

     H OPTION(*SRCSTMT : *NODEBUGIO) DFTACTGRP(*NO) ACTGRP(*CALLER)
     H BNDDIR('JSMBNDDIR')
      *
      * V6R1 - Limits
      * Maximum data structure size is 16,773,104 bytes
      * Data structure size = element size * occurrence
      *
     D ListDef1        S             60A   DIM(3) CTDATA
     D ListDefSize     S             10I 0 INZ(0)
     D ListEntSize     S             10I 0 INZ(0)
     D ListCount       S             10I 0 INZ(0)
     D ListMaxCount    S             10I 0 INZ(0)
      *
     D JSMHDL          S              4A   INZ(*BLANKS)
     D JSMSRV          S             50A   INZ(*BLANKS)
     D JSMSTS          S             20A   INZ(*BLANKS)
     D JSMMSG          S            512A   INZ(*BLANKS)
     D JSMCMD          S            512A   INZ(*BLANKS)
     D ZEROLENGTH      S             10I 0 INZ(0)
      *
     D COUNT           S              6S 0 INZ(0)
      *
     D LST1            DS                  OCCURS(9999)
     D  PRDID                        10A
     D  PRDNME                       20A
     D  PRDAMT                       10P 2
      *
     D LST2            DS                  DIM(9999) QUALIFIED
     D  PRDID                        10A
     D  PRDNME                       20A
     D  PRDAMT                       10P 2
      *
      * JSMX_BEGIN
      *
     C                   CALLB(D)  'JSMX_BEGIN'
     C                   PARM                    *OMIT
     C                   PARM                    ZEROLENGTH
      *
      * JSMX_OPEN - USE JSMCLTDTA FOR SERVER
      *
     C                   CLEAR                   JSMSRV
     C                   EVAL      JSMSRV = ''
     C                   CALLB(D)  'JSMX_OPEN'
     C                   PARM                    JSMHDL
     C                   PARM                    JSMSRV
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * SERVICE_LOAD
      *
     C                   CLEAR                   JSMCMD
     C                   EVAL      JSMCMD = 'SERVICE_LOAD' +
     C                                      ' SERVICE(ExcelService)' +
     C                                      ' TRACE(*YES)'
     C                   CALLB(D)  'JSMX_COMMAND'
     C                   PARM                    JSMHDL
     C                   PARM                    JSMCMD
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * CREATE
      *
     C                   CLEAR                   JSMCMD
     C                   EVAL      JSMCMD = 'CREATE'
     C                   CALLB(D)  'JSMX_COMMAND'
     C                   PARM                    JSMHDL
     C                   PARM                    JSMCMD
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * ADD OBJECT(*SHEET)
      *
     C                   CLEAR                   JSMCMD
     C                   EVAL      JSMCMD = 'ADD OBJECT(*SHEET)' +
     C                                      ' SHEET(MyTest)'
     C                   CALLB(D)  'JSMX_COMMAND'
     C                   PARM                    JSMHDL
     C                   PARM                    JSMCMD
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * ADD OBJECT(*CELLSTYLE)
      *
     C                   CLEAR                   JSMCMD
     C                   EVAL      JSMCMD = 'ADD OBJECT(*CELLSTYLE)' +
     C                                      ' TYPE(*NUMBER)' +
     C                                      ' COLUMN(5) RANGE(10,20)' +
     C                                      ' FONT(*TAHOMA)' +
     C                                      ' FORMAT(*FORMAT4)' +
     C                                      ' HALIGN(*RIGHT)' +
     C                                      ' BACKGROUND(*YELLOW)'
     C                   CALLB(D)  'JSMX_COMMAND'
     C                   PARM                    JSMHDL
     C                   PARM                    JSMCMD
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * WRITE LIST
      *
     C                   EVAL      COUNT = 0
     C     1             DO        20
     C                   ADD       1             COUNT
     C     COUNT         OCCUR     LST1
     C                   EVAL      PRDID  = 'ID' + %CHAR(COUNT)
     C                   EVAL      PRDNME = 'Product ' + %CHAR(COUNT)
     C                   EVAL      PRDAMT = 1000.45 + COUNT
     C                   ENDDO
      *
      * Reset list to beginning
     C     1             OCCUR     LST1
     C                   EVAL      ListDefSize  = %SIZE(ListDef1:*ALL)
     C                   EVAL      ListEntSize  = %SIZE(LST1)
     C                   EVAL      ListCount    = COUNT
     C                   EVAL      ListMaxCount = %ELEM(LST1)
     C                   CALLB(D)  'JSMX_BINDLST'
     C                   PARM                    JSMHDL
     C                   PARM                    ListDef1
     C                   PARM                    ListDefSize
     C                   PARM                    LST1
     C                   PARM                    ListEntSize
     C                   PARM                    ListCount
     C                   PARM                    ListMaxCount
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * WRITE R1C1
      *
     C                   CLEAR                   JSMCMD
     C                   EVAL      JSMCMD = 'WRITE R1C1(10,3)'
     C                   CALLB(D)  'JSMX_COMMAND'
     C                   PARM                    JSMHDL
     C                   PARM                    JSMCMD
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * WRITE LIST 2
      *
     C                   EVAL      COUNT = 0
     C     1             DO        20
     C                   ADD       1             COUNT
     C                   EVAL      LST2(COUNT).PRDID  = 'ID' + %CHAR(COUNT)
     C                   EVAL      LST2(COUNT).PRDNME = 'NME' + %CHAR(COUNT)
     C                   EVAL      LST2(COUNT).PRDAMT = 2000.47 + COUNT
     C                   ENDDO
      *
     C                   EVAL      ListDefSize  = %SIZE(ListDef1:*ALL)
     C                   EVAL      ListEntSize  = %SIZE(LST2)
     C                   EVAL      ListCount    = COUNT
     C                   EVAL      ListMaxCount = %ELEM(LST2)
     C                   CALLB(D)  'JSMX_BINDLST'
     C                   PARM                    JSMHDL
     C                   PARM                    ListDef1
     C                   PARM                    ListDefSize
     C                   PARM                    LST2
     C                   PARM                    ListEntSize
     C                   PARM                    ListCount
     C                   PARM                    ListMaxCount
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * WRITE R1C1
      *
     C                   CLEAR                   JSMCMD
     C                   EVAL      JSMCMD = 'WRITE R1C1(10,10)'
     C                   CALLB(D)  'JSMX_COMMAND'
     C                   PARM                    JSMHDL
     C                   PARM                    JSMCMD
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * READ LIST 2
      *
     C                   CLEAR                   LST1
     C                   CLEAR                   LST2
      *
     C                   EVAL      ListDefSize  = %SIZE(ListDef1:*ALL)
     C                   EVAL      ListEntSize  = %SIZE(LST2)
     C                   EVAL      ListCount    = 0
     C                   EVAL      ListMaxCount = %ELEM(LST2)
     C                   CALLB(D)  'JSMX_BINDLST'
     C                   PARM                    JSMHDL
     C                   PARM                    ListDef1
     C                   PARM                    ListDefSize
     C                   PARM                    LST2
     C                   PARM                    ListEntSize
     C                   PARM                    ListCount
     C                   PARM                    ListMaxCount
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * READ R1C1
      *
     C                   CLEAR                   JSMCMD
     C                   EVAL      JSMCMD = 'READ R1C1(10,15) ROWCOUNT(5)'
     C                   CALLB(D)  'JSMX_COMMAND'
     C                   PARM                    JSMHDL
     C                   PARM                    JSMCMD
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      *                  DSPLY                   ListCount
      *                  DO        LISTCOUNT     COUNT
      *                  EVAL      PRDID  = LST2(COUNT).PRDID
      *                  EVAL      PRDNME = LST2(COUNT).PRDNME
      *                  EVAL      PRDNME = %CHAR(LST2(COUNT).PRDAMT)
      *                  DSPLY                   LST2(COUNT)
      *                  DSPLY                   PRDNME
      *                  ENDDO
      *
      * SAVE FILE
      *
     C                   CLEAR                   JSMCMD
     C                   EVAL      JSMCMD = 'SAVE' +
     C                                      ' FILE(demo.xlsx)'
     C                   CALLB(D)  'JSMX_COMMAND'
     C                   PARM                    JSMHDL
     C                   PARM                    JSMCMD
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * CLOSE
      *
     C                   CLEAR                   JSMCMD
     C                   EVAL      JSMCMD = 'CLOSE'
     C                   CALLB(D)  'JSMX_COMMAND'
     C                   PARM                    JSMHDL
     C                   PARM                    JSMCMD
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * SERVICE_UNLOAD
      *
     C                   CLEAR                   JSMCMD
     C                   EVAL      JSMCMD = 'SERVICE_UNLOAD'
     C                   CALLB(D)  'JSMX_COMMAND'
     C                   PARM                    JSMHDL
     C                   PARM                    JSMCMD
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * JSMX_CLOSE
      *
     C                   CALLB(D)  'JSMX_CLOSE'
     C                   PARM                    JSMHDL
     C                   PARM                    JSMSTS
     C                   PARM                    JSMMSG
     C                   CALLP     checkSTS(JSMSTS:JSMMSG)
      *
      * JSMX_END
      *
     C                   CALLB(D)  'JSMX_END'
      *
     C                   SETON                                        LR

 
      ********************************
      * Procedure to check JSM status
      ********************************
     P checkSTS        B
     D checkSTS        PI              N
     D  csJSMSTS                           CONST LIKE(JSMSTS)
     D  csJSMMSG                           CONST LIKE(JSMMSG)
     D  csMSGTXT       S            512A
     C                   IF        csJSMSTS <> 'OK'
     C                   EVAL      csMSGTXT = %TRIM(csJSMSTS) + ' ' +
     C                                        %TRIM(csJSMMSG)
     C                   CALLP     sendMSG(csMSGTXT)
     C                   RETURN    *OFF
     C                   ENDIF
     C                   RETURN    *ON
     P                 E


      **************************************
      * Procedure to send a program message
      **************************************
     P sendMSG         B
     D sendMSG         PI
     D smMSGTXT                     512A   VALUE
     D smMSGT          S             10A   INZ('*DIAG')
     D smMSGI          S              7A   INZ('CPF9897')
     D smMSGF          S             20A   INZ('QCPFMSG   *LIBL     ')
     D smMSGL          S             10I 0 INZ(%SIZE(smMSGTXT))
     D smSTKE          S             10A   INZ('*')
     D smSTKC          S             10I 0 INZ(1)
     D smMSGK          S              4A   INZ(*BLANK)
     D smERRC          S             10I 0 INZ(0)
     C                   CALL      'QMHSNDPM'
     C                   PARM                    smMSGI
     C                   PARM                    smMSGF
     C                   PARM                    smMSGTXT
     C                   PARM                    smMSGL
     C                   PARM                    smMSGT
     C                   PARM                    smSTKE
     C                   PARM                    smSTKC
     C                   PARM                    smMSGK
     C                   PARM                    smERRC
     P                 E

 
**CTDATA ListDef1
PRDID                                             A000001000
PRDNME                                            A000002000
PRDAMT                                            P000001002
 

What does this example look like in LANSA’s RDMLX?


This example is self contained and requires no additional work besides compilation.
Function Options(*DIRECT)
*
Define Field(#PRDID) Type(*CHAR) Length(10)
Define Field(#PRDNME) Type(*CHAR) Length(20)
Define Field(#PRDAMT) Type(*DEC) Length(10) Decimals(2)
Define Field(#COUNT) Type(*DEC) Length(5) Decimals(0)
*
Def_List Name(#LST1) Fields(#PRDID #PRDNME #PRDAMT) Type(*WORKING)
*
* JSMX_BEGIN
*
Use Builtin(JSMX_BEGIN)
*
* JSMX_OPEN
*
Use Builtin(JSMX_OPEN) With_Args('LOCALHOST:7560') To_Get(#JSMXSTS #JSMXMSG #JSMXHDLE1)
Execute Subroutine(CHECK) With_Parms(#JSMXSTS #JSMXMSG)
*
* SERVICE_LOAD
*
#JSMXCMD := 'SERVICE_LOAD SERVICE(ExcelService) TRACE(*YES)'
Use Builtin(JSMX_COMMAND) With_Args(#JSMXHDLE1 #JSMXCMD) To_Get(#JSMXSTS #JSMXMSG)
Execute Subroutine(CHECK) With_Parms(#JSMXSTS #JSMXMSG)
*
* CREATE
*
#JSMXCMD := 'CREATE'
Use Builtin(JSMX_COMMAND) With_Args(#JSMXHDLE1 #JSMXCMD) To_Get(#JSMXSTS #JSMXMSG)
Execute Subroutine(CHECK) With_Parms(#JSMXSTS #JSMXMSG)
*
* ADD OBJECT(*SHEET)
*
#JSMXCMD := 'ADD OBJECT(*SHEET) SHEET(MyTest)'
Use Builtin(JSMX_COMMAND) With_Args(#JSMXHDLE1 #JSMXCMD) To_Get(#JSMXSTS #JSMXMSG)
Execute Subroutine(CHECK) With_Parms(#JSMXSTS #JSMXMSG)
*
* ADD OBJECT(*CELLSTYLE)
*
#JSMXCMD := 'ADD OBJECT(*CELLSTYLE) TYPE(*NUMBER) COLUMN(5) RANGE(10,20) FONT(*TAHOME) FORMAT(*FORMAT4) HALIGN(*RIGHT) BACKGROUND(*YELLOW)'
Use Builtin(JSMX_COMMAND) With_Args(#JSMXHDLE1 #JSMXCMD) To_Get(#JSMXSTS #JSMXMSG)
Execute Subroutine(CHECK) With_Parms(#JSMXSTS #JSMXMSG)
*
* WRITE LIST
*
Begin_Loop Using(#COUNT) To(20)
#PRDID := 'ID' + #COUNT.AsString
#PRDNME := 'Product' + #COUNT.AsString
#PRDAMT := 2000.45 + #COUNT
Add_Entry To_List(#LST1)
End_Loop
*
#JSMXCMD := 'WRITE R1C1(10,3)'
Use Builtin(JSMX_COMMAND) With_Args(#JSMXHDLE1 #JSMXCMD) To_Get(#JSMXSTS #JSMXMSG #LST1)
Execute Subroutine(CHECK) With_Parms(#JSMXSTS #JSMXMSG)
*
* READ LIST
*
Clr_List Named(#LST1)
*
#JSMXCMD := 'READ R1C1(10,3) ROWCOUNT(5)'
Use Builtin(JSMX_COMMAND) With_Args(#JSMXHDLE1 #JSMXCMD) To_Get(#JSMXSTS #JSMXMSG #LST1)
Execute Subroutine(CHECK) With_Parms(#JSMXSTS #JSMXMSG)
*
Selectlist Named(#LST1)
* Display Fields(#PRDID #PRDNME #PRDAMT)
Endselect
*
* SAVE FILE
*
#JSMXCMD := 'SAVE FILE(demo.xlsx)'
Use Builtin(JSMX_COMMAND) With_Args(#JSMXHDLE1 #JSMXCMD) To_Get(#JSMXSTS #JSMXMSG)
Execute Subroutine(CHECK) With_Parms(#JSMXSTS #JSMXMSG)
*
* CLOSE
*
#JSMXCMD := 'CLOSE'
Use Builtin(JSMX_COMMAND) With_Args(#JSMXHDLE1 #JSMXCMD) To_Get(#JSMXSTS #JSMXMSG)
Execute Subroutine(CHECK) With_Parms(#JSMXSTS #JSMXMSG)
*
* SERVICE_UNLOAD
*
Use Builtin(JSMX_COMMAND) With_Args(#JSMXHDLE1 'SERVICE_UNLOAD') To_Get(#JSMXSTS #JSMXMSG)
Execute Subroutine(CHECK) With_Parms(#JSMXSTS #JSMXMSG)
*
* JSMX_CLOSE
*
Use Builtin(JSMX_CLOSE) With_Args(#JSMXHDLE1) To_Get(#JSMXSTS #JSMXMSG)
Execute Subroutine(CHECK) With_Parms(#JSMXSTS #JSMXMSG)
*
* JSMX_END
*
Use Builtin(JSMX_END)
*
* SUB ROUTINES
*
Subroutine Name(CHECK) Parms((#JSMXSTS *RECEIVED) (#JSMXMSG *RECEIVED))
*
If Cond('#JSMXSTS *NE OK')
*
Use Builtin(JSMX_CLOSE) With_Args(#JSMXHDLE1) To_Get(#JSMXSTS #JSMXMSG)
*
Menu Msgtxt('Java service error has occurred')
*
Endif
*
Endroutine
 

You can find these two and other examples built in RPG and RDMLX in the LANSA documentation.

Can Visual LANSA solve issues with app development in RPG programming language?

Visual LANSA is a low-code development platform available for free. It is feature-rich. It enables you to simplify the development process. You can use Visual Lansa to quickly modernize legacy apps. It gives you access to a low-code method. Hence, you can easily build apps and deploy them to IBM i.

Also, you donโ€™t have to learn RPG programming language to use it. You donโ€™t even need to learn other languages, like Java. You can do everything from defining to deploying app logic with LANSA low-code tools. Also, it has a strong community support. Overall, it offers a great solution for effectively developing and modernizing apps. Therefore, you should definitely consider using Visual LANSA.

LANSA is a high-productivity development platform for modernizing IBM i applications. It enables thousands of developers to accelerate app development workflow and optimize business processes. Try it now for free.

Future-proof software
for digital success

ABOUT THE AUTHOR

LANSA Editors

LANSA is a professional low-code development platform that helps businesses efficiently build and modernize software. In this blog, the team draws on decades of experience empowering enterprises to innovate on the IBM i and future-proof their mission-critical systems.

More Articles

Are you ready for better conversations?

Integrated solutions that deliver powerful results.

Keep the light on.

Join our mailing list for development guides and solutions for constant IT innovation.