EGL Development User Group

EGL Development User Group

EGL Development User Group

The EGL Development User Group is dedicated to sharing news, knowledge, and insights regarding the EGL language and Business Developer product. Consisting of IBMers, HCL, and users, this community collaborates to advance the EGL ecosystem.

 View Only
Expand all | Collapse all

Accessing IBM i programs as web services error

  • 1.  Accessing IBM i programs as web services error

    Posted Thu December 03, 2015 08:21 AM

    Hi, I'm try to access IBM i program as web services.

    I'm looking here: http://www-01.ibm.com/support/knowledgecenter/SSMQ79_9.5.0/com.ibm.egl.pg.doc/topics/pegl_iseries_program_as_service.html

    But when i'm try  to call the ws he WAS(websphere 8.5 in standard configuration) send me this error:

    [26/11/15 12.19.34:467 CET] 0000009b SystemErr R 26/nov/2015 12:19:34.3 EGL1540E:EGL1540E Si è verificata un'eccezione durante la chiamata di servizio REST. Binding: eglBinding, Operazione :eglBinding

    EGL0001I L'errore si è verificato in EGL REST Service servlet.

    detail1:500

    detail2:FAILED

    detail3:EGL0010E Dipendenza esterna mancante. Si è verificata la seguente eccezione. Eccezione: java.lang.NoClassDefFoundError: com.ibm.as400.access.ErrorCompletingRequestException

    EGL0001I L'errore si è verificato in MUWSDL.

    [26/11/15 12.19.34:467 CET] 0000009b SystemErr R 26/nov/2015 12:19:34.4 EGL1540E:EGL1540E Si è verificata un'eccezione durante la chiamata di servizio REST. Binding: eglBinding, Operazione :eglBinding

    EGL0001I L'errore si è verificato in EGL REST Service servlet.

    detail1:500

    detail2:FAILED

    detail3:EGL0010E Dipendenza esterna mancante. Si è verificata la seguente eccezione. Eccezione: java.lang.NoClassDefFoundError: com.ibm.as400.access.ErrorCompletingRequestException

    EGL0001I L'errore si è verificato in MUWSDL.

     

    Here the EGL project source: https://drive.google.com/open?id=0B09Oixe6seVSVEpqaXFxMUxudDg

    In attachment below the document with detailed steps with RPG program source.

    Some ideas??

    Matteo@MR


  • 2.  Re: Accessing IBM i programs as web services error

    Posted Thu December 03, 2015 09:49 AM

    Hi,

    It sounds like something related to the jt400.jar not being found.   Here is an old link that may apply.

     

    http://stackoverflow.com/questions/24157953/websphere-application-server-v8-5-liberty-profile-accessing-iseries

    markevans


  • 3.  Re: Accessing IBM i programs as web services error

    Posted Fri December 04, 2015 05:21 AM

    Thanks Mark, If I understand correctly to resolve the problem I should add

    <classloader commonLibraryRef="DB2iToolbackLib"/> to the server.xml file.

    This is the way? 

    But I can't find the file on Webshere 8.5.

    Windows's search tells me that in my system there are more than 10 files with that name. Where is the right one?

    Matteo@MR


  • 4.  Re: Accessing IBM i programs as web services error

    Posted Fri December 04, 2015 04:13 PM

    Matteo,

     

    I am not a WebSphere Liberty  expert, but from reading the info in that post, it would seem DB2iToolBoxLib referred to a "<library>" reference listed earlier in the post that defined where the jt400.jar was located.

    That said, as background, EGL uses the classes in the jt400.jar (the IBM Toolbox for Java)  to do the calls as this provides the remote access classes to the IBM i machine.

     

    In your case, I think you are using WAS 8.5 vs WAS Liberty 8.5   Before I would make any changes to WAS, I would try to add a jt400.jar to the WebContent->WEB_INF->lib folder and redeploy/republish it.    Doing this normally adds the jt400.jar to your "CLASSPATH" and it will be able to find the required classes.

     

    You should be able to find the jt400.jar in the RBD 9.5 plugins under the datatools folders, on your IBM i machine (under /QIBM/ProdData/HTTP/Public/jt400/lib), or you can download the open source version (JTopen) from SourceForge.  Basically use Google to get a location if you don't want to get from the RBD plugins or off the IBM i machine.  I would suggest using one of the IBM versions from RBD or the IBM i. 

     

    take care.

     

    Mark

     

     

    markevans


  • 5.  Re: Accessing IBM i programs as web services error

    Posted Wed December 09, 2015 11:26 AM

    Thanks Mark!!!!

    Now the problem is that the response from the service is nothing (empty string).
    But that value is not returned to the callback. Where is the problem? Maybe something wrong with the PGM MUWSDL? 

    Here the current project: https://drive.google.com/open?id=0B09Oixe6seVSWFFuQjJvaWxVcGM

    P.S. I added the MonitorService tool of Dojo to see data service calls 

    Matteo@MR


  • 6.  Re: Accessing IBM i programs as web services error

    Posted Wed December 09, 2015 04:35 PM

    I tried to download but it said I did not have permission to access.   I used my personal gmail account and requested access.

    Mark

    markevans


  • 7.  Re: Accessing IBM i programs as web services error

    Posted Wed December 09, 2015 04:39 PM

    Also, can you check to see if you had any failure in the joblog of the server job that handles remote calls.   Maybe an authority error or something else.  

     

    And what do you consider the problem. 

    - Are you expecting the service to return an empty string, but this is not being returned in the callback?

    - That the service just returned an empty string vs real data?

     

     

    markevans


  • 8.  Re: Accessing IBM i programs as web services error

    Posted Thu December 10, 2015 08:28 AM

    OK Mark,  I solved by setting the two parameters of RPG PGM as input output type. 

    BEFORE

    ...

    dmuwsdl           pr
    d CodiceCliente                       like(cdutente) const
    d DimmiChiSei                  100                                         Dati restituiti
    dmuwsdl           pi
    d CodiceCliente                       like(cdutente) const
    d DimmiChiSei                  100                                         Dati restituiti

    ....

     

    AFTER

    ....

    dmuwsdl           pr
    d CodiceCliente                       like(cdutente)
    d DimmiChiSei                  100                                         Dati restituiti
    dmuwsdl           pi
    d CodiceCliente                       like(cdutente)
    d DimmiChiSei                  100                                         Dati restituiti

    ....

     

    Now the last thing to fix is how to modify the attributes of shared protocols used to connect to the service.

    I would like to set "userid", "password" and "library" dynamically to access a PGM at the correct point (in the Deploy Description Overview I set library = MUTES, userid = MUT and password = xxxxx).

    How do I set the username MUT2 and password xxxxx for MUTES2 library with MUT2 for set the specific data access library before the call? 

    I tried with ServiceLib.setHTTPBasicAuthentication (srv, user, password) but I see no change. 

     

    Matteo@MR


  • 9.  Re: Accessing IBM i programs as web services error

    Posted Thu December 10, 2015 02:00 PM

    Hi,

    Glad you got it to work.  I am not an RPG programmer, so probably would not have caught it.

    On security, when invoking it as a REST service, I don't see a way to set the userid/password dynamically.  If you invoke it as a SOAP service, you can try the ServiceLib.setHTTPBasicAuthentication (srv, user, password), but from reading some on PCML, it seems to require some "static" userid/password setup.

    A couple of other options and both would need the application to be 3 tiers meaning,  RUI(Javascript)->EGL Service(Java in WAS/Tomcat)->RPG program

    a.) In the EGL Service, use syslib.setRemoteUser(userid, password) and invoke the interface/hostprogram you created already, but issue this before the invocation of the RPG interface. 

    b.) In the EGL service, use a call "RPGProgram" and just call it rather than invoking it as a service and using PCML.    This is documented in the IBM i Application Modernization Redbook in the EGL chapter.    Also, if you could get a hold of Joe Pluta's book named "Developing Web 2.0 applications with EGL for IBM i", this is the technique he uses as well.  The book is for RBD 7.5, but still has good concepts.   This technique would also allow the use of syslib.setRemoteUser.

     

    Mark

     

     

    markevans


  • 10.  Re: Accessing IBM i programs as web services error

    Posted Mon January 18, 2016 04:17 AM


  • 11.  Re: Accessing IBM i programs as web services error

    Posted Thu January 19, 2017 05:24 AM

    Hi, I have another problem to solve on this subject.

    In my project I access IBMi programs as web services like this http://www.ibm.com/support/knowledgecenter/en/SSMQ79_9.5.1/com.ibm.egl.pg.doc/topics/pegl_iseries_program_as_service.html.

    Everything works fine!

    In the RUI Handler I'm calling the programm as a web service like this:

    package it.mr.galileo.handlers;// RUI Widgetimport com.ibm.egl.rui.infobus.InfoBus;import com.ibm.egl.rui.widgets.Box;import com.ibm.egl.rui.widgets.DataGrid;import com.ibm.egl.rui.widgets.DataGridBehaviors;import com.ibm.egl.rui.widgets.DataGridColumn;import com.ibm.egl.rui.widgets.DataGridLib;import com.ibm.egl.rui.widgets.DataGridSelector;import com.ibm.egl.rui.widgets.DataGridSorter;import com.ibm.egl.rui.widgets.Div;import com.ibm.egl.rui.widgets.HTML;import com.ibm.egl.rui.widgets.TextLabel;import egl.ui.rui.Event;import egl.ui.rui.Widget;import dojo.widgets.DojoDialog;import it.mr.galileo.controller.Navigation;import it.mr.galileo.controller.UIError;import it.mr.galileo.lib.Application;import it.mr.galileo.lib.DojoDialogLib;import it.mr.galileo.srv.ILettureSrv;import it.mr.galileo.srv.In_LET;import it.mr.galileo.srv.Out_LET;import it.mr.galileo.srv.Out_LET_dati;//handler Letture type RUIWidget {targetWidget = content, onConstructionFunction = onConstruction ,   cssFile="css/PortaleRUI.css", @VEWidget{ category = "Custom" }}        private rich In_LET;        private resp Out_LET;        private letture Out_LET_dati[];        private srv ILettureSrv {@BindService};        titolo1 TextLabel{text = "Elenco letture utenza -> ", class = "text14" };        titolo2 TextLabel{text = "", class = "text14", fontWeight = "bold" };        //sorts the rows lexicographically by the elements in the selected column        gridSorter DataGridSorter {};                        //highlights the row selected        gridSelector DataGridSelector { color = "lightgreen" };        grid DataGrid {                marginLeft=10,                behaviors = [                                 hideCol,                                 addEditors,                                centerColumns,                                DataGridBehaviors.tightCells                ],                headerBehaviors = [                                intesta,                                 hideCol,                                 centerColumns,                                DataGridBehaviors.grayCells                            //gridSorter.columnSorter                ],                columns = [                        new DataGridColumn { name = "Matricola",               displayName = "Matricola [Correttore]",           width = 150,    headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                        new DataGridColumn { name = "QtaContatore",                displayName = "Qta Attuale Contatore",                width = 100,    headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                        new DataGridColumn { name = "QtaCorrettore",               displayName = "Qta Attuale Correttore",       width = 100,    headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                        new DataGridColumn { name = "QtaContatoreP",               displayName = "Qta Precedente Contatore",     width = 120,    headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                        new DataGridColumn { name = "QtaCorrettoreP",              displayName = "Qta Precedente Correttore",    width = 120,    headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                        new DataGridColumn { name = "QtaConsumoContatore",         displayName = "Consumo Contatore",            width = 100,    headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                        new DataGridColumn { name = "QtaConsumoCorrettore",        displayName = "Consumo Correttore",           width = 150,    headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                         new DataGridColumn { name = "DtLetture",                   displayName = "Data Lettura",                                 width = 80,             headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                        new DataGridColumn { name = "DtIniPer",                    displayName = "Data Inizio Periodo",          width = 80,             headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                        new DataGridColumn { name = "RifDocFatturazione",  displayName = "Fattura",                                      width = 130,    headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                        new DataGridColumn { name = "TipoLettura",                 displayName = "Tipo Lettura",                         width = 90,     headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                        new DataGridColumn { name = "CoefCorr",                displayName = "Coefficiente Correttivo",  width = 95,     headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                        new DataGridColumn { name = "StatoLettura",                displayName = "Stato Lettura",                                width = 95,     headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER},                        new DataGridColumn { name = "RifDocAnnRett",               displayName = "Documento Annulla/Rettifica",width = 130,      headerAlignment = DataGridLib.ALIGN_CENTER,     alignment = DataGridLib.ALIGN_CENTER}                        ],                selectionMode = DataGridLib.SINGLE_SELECTION, enableSorting = no,                pageSize = 15,                showScrollbar = yes,                showButtonBar = no,                 style = "overflow-x: scroll; overflow-y: scroll;",                data = (letture as any[])        };                //Main container    content Div { children = [ ui], id = "Letture"};                 div1 Div {columns = 1, children = [new Box{columns = 3, children = [titolo1,new HTML{width = 10}, titolo2], marginBottom = 40, marginLeft = 10}]};        div3 Div {columns = 1, children = [grid]};                // The UI.        ui Div {                columns = 1,                children = [                        div1,                        div3                        ]};                                //Alcuni eventi per il render della griglia        function addEditors(grid DataGrid in, cell Widget in, row any in, rowNumber int in, column DataGridColumn in)          //                    end          function centerColumns(grid DataGrid in, cell Widget in, row any in, rowNumber int in, column DataGridColumn in)                 cell.style = "text-align: center; word-wrap: break-word; white-space: normal";        end        function hideCol(grid DataGrid in, cell Widget in, row any in, rowNumber int in, column DataGridColumn in)           //        end                     function intesta(grid DataGrid in, cell Widget in, row any in, rowNumber int in, column DataGridColumn in)                cell.height = "30px";                case            when (column.name == "QtaContatore")                    cell.innerHTML = "Quantità Attuale<br>Contatore";                when (column.name == "QtaCorrettore")                    cell.innerHTML = "Quantità Attuale<br>Correttore";                   when (column.name == "QtaContatoreP")                    cell.innerHTML = "Quantità Precedente<br>Contatore";                when (column.name == "QtaCorrettoreP")                    cell.innerHTML = "Quantità Precedente<br>Correttore";                when (column.name == "QtaConsumoContatore")                    cell.innerHTML = "Consumo<br>Contatore";                when (column.name == "QtaConsumoCorrettore")                    cell.innerHTML = "Consumo<br>Correttore";                when (column.name == "DtLetture")                    cell.innerHTML = "Data<br>Lettura";                when (column.name == "DtIniPer")                    cell.innerHTML = "Data<br>Inizio Periodo";                when (column.name == "CoefCorr")                    cell.innerHTML = "Coefficiente<br>Correttivo";                    when (column.name == "RifDocAnnRett")                    cell.innerHTML = "Documento<br>Annulla/Rettifica";                                    end        end                     function onConstruction()                InfoBus.subscribe(Application.CONST_LETTURE_CALLBACK, lettureCallback);        end                     function start(cliente string)                if (cliente != "");                        carica();                       end        end                     function lettureCallback (event string in, data any in)                titolo2.text = Navigation.currentSession.cliente.cCodiceCliente + " - " + Navigation.currentSession.descrCliente;                cdcli string = data as string;                start(cdcli);        end                                //Carica letture cliente        function carica()                //Dati input                rich.CodiceCliente = Navigation.currentSession.cliente.cCodiceCliente;                uri string = Application.CONST_BASE_SRV_URL + "MUPW20LET";                serviceLib.setRestServiceLocation(srv,uri);                call srv.letture(rich, resp) returning to srvReturn onException displayException { Timeout = 5000 };         end                function displayException(ex AnyException in)                closeProgressDialog();               error UIError {origin="Eccezione servizio caricamento letture",exception=ex};               showErrorDialog(error);    end                function srvReturn(ric In_LET in, res Out_LET in)                closeProgressDialog();                servicelib.endStatefulServiceSession(srv, displayException);                try                        // Carica le letture nella grid (eventualmente resta vuota)                        numElem int = res.datiN;                        res.dati.resize(numElem);                        //Dati in GRID                        grid.data = res.dati as any[];                  onException (exc AnyException)                        closeProgressDialog();                error UIError {origin="Eccezione caricamento griglia letture",exception=exc};                showErrorDialog(error);                end         end                function showMessageDialog(title string in, message string in)        DojoDialogLib.showMessage(title, message, buttonClicked);           end        function showWarningDialog(title string in, message string in)        DojoDialogLib.showWarning(title, message, buttonWarningClicked);    end            function showErrorDialog(error UIError in)              s string = error.exception.message;        if(exp isa ServiceInvocationException)            s += "\nDettaglio1: " +(error.exception as serviceInvocationException).detail1;            s += "\nDettaglio2: " +(error.exception as serviceInvocationException).detail2;            s += "\nDettaglio3: " +(error.exception as serviceInvocationException).detail3;        end        DojoDialogLib.showError(error.origin, s, buttonClicked);    end         function buttonWarningClicked(id String in, e Event in) returns (boolean)        Navigation.currentSession = null;        Navigation.toLogin();                return (true);        end                function buttonClicked(id String in, e Event in) returns (boolean)                      return (true);        end                private progressDialog DojoDialog;                      function showProgressDialog()            progressDialog = DojoDialogLib.showProgress("Letture cliente", "Caricamento dati in corso...", false, buttonClicked);        end                private function closeProgressDialog()                 if (progressDialog != null)                        progressDialog.hideDialog();                end        end     end

    The program is called and does its job responding as it should. The library is set according to the USERID and PASSWORD saved in the protocol in the EGL Deployment Descriptor:

     

    Ok, now I'm trying to set a different USERID and PASSWORD for to change a program resident library on-demand.

    New capabilities are introduced in Rational® Business Developer V9.5.1 including one specification to solve my request:

    https://www.ibm.com/developerworks/community/blogs/3e2b35ae-d3b1-4008-adee-2b31d4be5c92/entry/Rational_Business_Developer_9_5_1_is_now_available?lang=en

    So I added this code in my source for set a specific USERID before to invoke he call to a rogramm:

            function carica()                //Dati input                rich.CodiceCliente = Navigation.currentSession.cliente.cCodiceCliente;                uri string = Application.CONST_BASE_SRV_URL + "MUPW20LET";                user string = "RCGMASTER";                pass string = "*********";                serviceLib.setHTTPBasicAuthentication(srv, user, pass);                serviceLib.setRestServiceLocation(srv,uri);                call srv.letture(rich, resp) returning to srvReturn onException displayException { Timeout = 5000 };              end

    But the result is the same, the calling the program is ALWAYS whit the USERID=TUGMASTER (that recorded into the protocol in EGL Deployment Descriprtor).

    Where's the fault/problem?

    @Marcel-D @markevans @Niek_Vandael some ideas??

    Matteo@MR