Simplified Queries of SAP Tables From Java

17

Click here to load reader

description

Access SAP from Java programming

Transcript of Simplified Queries of SAP Tables From Java

  • Simplified Queries of SAP Tables from JavaBy Jay Brown and Steve Renard (Colgate-Palmolive)

    This article discusses how to easily query SAP tables in your SAP Portal applications. It is divided intotwo parts; the first part discusses the implementation and use of the Java classes that expose the SAP data.The second part discusses enhancing the backend function to suit your companys functionality andsecurity needs.

    Any Java based SAP Enterprise Portal application that communicates with R/3 will almost certainly useRFCs and BAPIs to perform its work on the backend system. Suppose you want to write an ESSapplication to allow an employee to change her HR personal data. You would most likely use the standardBAPI_PERSDATA_CHANGE function module to make the changes in SAP. This BAPI, like most, hasparameters that have a defined set of valid values, which are stored in SAP tables.

    As an example, lets use the BAPI_PERSDATA_CHANGE Import Parameter MARITALSTATUS, whichspecified the employees marital status. In your application, you would provide a drop-down list controlwith the various values (Married, Single, etc). This import parameters valid values are stored in theMarital Status Designators table, which is table T502T. In your application, you may choose to supply thisfields valid options in a couple of ways:

    1. Hard-code the values in the application. In the beginning, this would seem to be the fastest solution.In the long term, this is a very bad idea. If new values are added or deleted, you will need to modifyyour code.

    2. Code a custom RFC to perform the SELECT statement against the desired R/3 table. This is a moretraditional way that keeps your applications options in sync with the back-end systems.Unfortunately, this can become a maintenance burden as more tables need to be read and more customRFCs need to be developed.

    To handle this problem, we attempted to use the Function Module RFC_READ_TABLE. This RFC willquery the specified table in the R/3 system and return the results in an unformatted table. Optionally, youmay also specify the field names to return, the number of rows to return, as well as a selection (WHERE)clause. Because the result set is unformatted, the data need to be parsed for them to be usable. Ideally, wewould like a JCO Table to be created that accurately reflects the table structure and data from the response.Having the data in a JCO Table allows us to use it in many tasks, such as displaying the data in a tableViewcontrol on the Portal. Below is a simple illustration of how the table data are returned:

  • As you can see, the requested tables fields are returned as a single row in the DATA table. Fortunately,the FIELDS table describes the data table, so we can parse out each field.

    We decided to develop a wrapper class called R3Table to hide the gory details of theRFC_READ_TABLE function module. We have also made our own custom version ofRFC_READ_TABLE, called ZRFC_READ_TABLE. You can use R3Table class even if you dontimplement your own custom version of ZRFC_READ_TABLE, but youll probably want to when you readmore about it the section RFC_READ_TABLE vs. ZRFC_READ_TABLE later in this document. If youdecide to implement the ZRFC_READ_TABLE, be sure to change the READ_TABLE_FUNCTION_NAMEstatic variable (in R3Table.java) to contain the name of your custom function ZRFC_READ_TABLE.

    The R3Table factory class is a subclass of JCO.Table. To use it, you must invoke one of the getInstancemethods to create an instance of the class. There are many forms of the getInstance method to allow you tospecify the fields to return, the maximum number of rows to return, the starting row, and the where clause.Refer to the JavaDoc for details. The most basic getInstance documentation is listed below.

    Public static R3Table getInstance(com.sap.mw.jco.JCO.Client client, Java.lang.String tableName) throws R3TableException, com.sap.mw.jco.JCO.Exception

    Method getInstance Short Form. Instantiates a R3Table class populated with thedata selected from the specified table. Returns ALL rows, ALL fields, withoutskipping.

    Parameters:

    Client An already connected JCO.Client.

    tableName - SAP Table to query.

    For example, to load ALL rows and fields from SAP Table T502T: ...client = clientService.getJCOClient("SAP_HR_SYS", request);client.connect();R3Table table = R3Table.getInstance(client, "T502T");...

    Returns:

    R3Table

    Example.The following basic example gets and connects a JCO Client to the SAP_HR_SYS system. Aftersuccessfully connecting, it gets an instance of R3Table populated with all rows and fields from the T502Ttable on the SAP_HR_SYS system.

    try {IportalComponentRequest request = (IportalComponentRequest)

    this.getRequest();JCO.Client client = null;IJCOClientService clientService = (IJCOClientService)

    request.getService(IJCOClientService.KEY);

  • Client = clientService.getJCOClient("SAP_HR_SYS", request); Client.connect();R3Table table = R3Table.getInstance(client, "T502T");System.out.println(table.toString());

    }catch (Exception e) {e.printStackTrace();

    }

    finally {if (client != null)client.disconnect();

    }

    Output: The R3Table.toString() output shows the information about the R3Table populated from theT502T table.

    Fetch Function: RFC_READ_TABLEWhere Clause:Max Rows: AllDelimiter: |Query Response Time (ms): 531Skip Count: 0Fields: FTEXT, MANDT, SPRSL, FAMST-----------| TABLE 'T502T'-----------| MA| | | FTEXT|-----------|012|3|4|567890|-----------|151|1|0|Single||151|1|1|Marr. ||151|1|2|Wid. ||151|1|3|Div. ||151|1|4|NM ||151|1|5|Sep. |... ...

    To use R3Table in the real world, you would want to pass its data along to an HTMLB control such as adropdownListBox or tableView. To do this, you simply construct one of the List Model classes (seebelow) and pass it to your control. The R3TableDemo example below illustrates this by constructing aJCOTableViewModel and passing it to an HTMLB tableView control.

    Flow of R3TableDemo Portal Component

  • The R3TableDemo IView

    This IView simply gets an instance of an R3Table filled with data from the T502T table, and creates aJCOTableViewModel object that will be used by the tableView control in the JSP file.

    Code excerpt. See full example code at the end of this document.In your Bean In your JSP// Getter method for tableListModelpublic JCOTableViewModelgetTableListModel() {R3Table table =

    R3Table.getInstance(client,tName);Return new JCOTableViewModel(table);}

    List Models on the PDK that use JCO Table:http://localhost:8080/irj/services/htmlb/docs/api/com/sapportals/htmlb/JCOChartModel.htmlhttp://localhost:8080/irj/services/htmlb/docs/api/com/sapportals/htmlb/JCOListModel.htmlhttp://localhost:8080/irj/services/htmlb/docs/api/com/sapportals/htmlb/table/JCOTableViewModel.html

  • RFC_READ_TABLE vs. ZRFC_READ_TABLE

    There are a few reasons why you might want to consider making your own copy of the functionRFC_READ_TABLE in your R/3 system(s). The most compelling of these reasons is security. If the usersof your external applications are only making connections to R/3 under their own R/3 user IDs, then youmust give fairly broad access to each of these users when using RFC_READ_TABLE. Rather than givingout this broad access to a large group of people, another option would be to use 2 types of connectionswithin your applicationone connection under the users own ID for normal RFC or BAPI calls that arerequired, and the other connection under a generic ID for calling RFC_READ_TABLE. Neither of theseoptions is appealing. A third more attractive option that is much easier to implement is to create your owncopy of RFC_READ_TABLE and make some minor modifications. Below are 3 reasons to considercreating your own copy of RFC_READ_TABLE in your R/3 system(s), along with some details on acouple of changes you might want to consider.

    1. SecurityThe very first action of the function RFC_READ_TABLE is to call another function named,VIEW_AUTHORITY_CHECK. At first glance, this seems harmless. The name of the table to be read ispassed, along with a view option of S (which one would assume to represent, viewing, or, reading).However, if you drill-down into the function VIEW_AUTHORITY_CHECK and look through its sourcecode, you will discover that it is ultimately doing a check on the authorization object S_TABU_DIS.

    The security object S_TABU_DIS checks against the users authorization to perform an action (read,change, create records, etc.) on tables belonging to a particular table classIt is not checking authorizationfor an individual table. What this means for you as an application developer is that the users of yourapplication will need to have access to the table class or classes to which the table or tables belong, for anytables that are being read by RFC_READ_TABLE. A single table class can have thousands of tables asmembers, so in some cases you must give your users read access to thousands of tables so they can simplyread a single table. This is something your security group will certainly frown upon if they understand thesecurity object S_TABU_DIS, or if you bring it to their attention. As mentioned above, you could use ageneric ID for R/3 connections when calling RFC_READ_TABLE, but as a long term solution lookingforward to many applications using RFC_READ_TABLE, this would require a lot of extra work.

    2. DATA_BUFFER_EXCEEDEDThe function RFC_READ_TABLE reads table records into a table with the structure TAB512. As thename somewhat indicates, this table has a single field with the length of 512 characters. This means youare limited to reading a combination of fields from your table that does not exceed 512 characters in width.In most cases, if you are limiting your call to the specific fields you need, this should not be a problem.However, you should be aware of this limitation. Exceeding 512 characters in width will result in anexception of DATA_BUFFER_EXCEEDED.

    3. As of 4.6c, RFC_READ_TABLE is not Released to CustomersO.K. This last reason is pretty weak. The fact that a function module is not released seldom stopsanyone from using it. If its interface changes in the future, though, just keep in mind, I told you so.

    Copying ZRFC_READ_TABLE and Changes You may want to ConsiderSince RFC_READ_TABLE is the only function that belongs to the function group SDTX, it is a piece ofcake to copy. Simply go to transaction SE38, and copy the program SAPLSDTX. When you are promptedfor a new function group name, enter ZSDTX. If you have never copied a function group like this before,you should not be alarmed that you are creating a new program that does not begin with, Z. The functiongroup you create will have the name, SAPLZSDTX. As part of the copy process, you will be directed tonow copy the functions that belong to the group. Since there is only 1 function, this is very simple. Justenter the name ZRFC_READ_TABLE. Again, since there is only 1 function in this group, you do not needto worry about cross references between functions in your new group, which gets pretty complicated forlarger function groups.

  • Security ChangesAfter activating your new group, you should have a fully functional copied function module with the name,ZRFC_READ_TABLE. Now you are free to make any changes you desire. The first change you shouldconsider on the authorization check that is performed. Rather than calling the functionVIEW_AUTHORITY_CHECK, you might want to create your own authorization object that is checked byindividual table, and use it instead. For example, replace the following code:

    --------------------------------------------------------------------------------------------------------------------------------call function 'VIEW_AUTHORITY_CHECK' exporting view_action = 'S' view_name = query_table exceptions no_authority = 2 no_clientindependent_authority = 3 table_not_found = 4.

    if sy-subrc = 2 or sy-subrc = 3. raise not_authorized.elseif sy-subrc = 1. raise table_not_available.endif.--------------------------------------------------------------------------------------------------------------------------------

    with this:

    --------------------------------------------------------------------------------------------------------------------------------DATA: tabname LIKE dd02l-tabname.

    SELECT SINGLE tabname FROM dd02l INTO tabname WHERE tabname EQ query_table AND as4local EQ 'A'.

    IF sy-subrc NE 0. RAISE table_not_available. ENDIF.

    AUTHORITY-CHECK OBJECT 'Z_TABL_MNT' ID 'ACTVT' FIELD '03' ID 'TABLE' FIELD query_table.

    IF sy-subrc NE 0. RAISE not_authorized. ENDIF.--------------------------------------------------------------------------------------------------------------------------------

    The authorization object Z_TABL_MNT could be defined as follows:

  • This list of permitted activities is completely up to you. If you are only using this security object forZRFC_READ_TABLE, you only need a permitted activity of display. However, this security object mightbe useful in many other places, so you could add a full list of activities.

    Avoiding the Exception DATA_BUFFER_EXCEEDEDIf you need more space than the allotted 512 characters for you table records, you can change the referencetype of the functions table parameter DATA from TAB512 to some other similar structure having a single,larger character field. Anyone familiar with searching the R/3 data dictionary (transaction SE11) should beable to find a similar table with a larger character field in a matter of a few minutes. Simply swap thenewfound table or structure into the reference type for DATA using the function builder (transaction.SE37). If you cannot find a suitable standard table or structure for your needs, you can simply create yourown using SE11. You should keep in mind that as you increase the size of your record buffer, theperformance of your function will wane. That can be a very critical issue for web applications.

    We welcome any suggestions of other standard function modules that could be used for the purpose ofgenerically reading tables from applications external to R/3, or any standard security object that could beused for limiting read access by individual tables.

    [email protected][email protected]

  • R3Table.javapackage com.colpal.util.portal;

    import java.util.HashMap;import java.util.Iterator;import java.util.StringTokenizer;import com.sap.mw.jco.IFunctionTemplate;import com.sap.mw.jco.IMetaData;import com.sap.mw.jco.IRepository;import com.sap.mw.jco.JCO;/** * @version 1.0, 08/20/2003 * @author J. Brown * Colgate-Palmolive * * Utility class to facilitate simple access to SAP Tables. *

    * The intention of this class is to enable Enterprise Portal applications * to load drop-down values into fields at runtime instead of hard-coding the * values in the application. * *

    * *The steps to use this class are as follows: * *Obtain a JCO.Client to the desired SAP. *Connect the Client. *Use one of the getInstance() methods of this class to create a R3Table loaded withyour favorite data. *Create a Model, such as JCOListModel to be used in your JSP. * *

    *...

    *client = clientService.getJCOClient("SAP_HR_SYS", request); *client.connect(); *R3Table table = R3Table.getInstance(client, "T002"); *...

    * *

    *

    * JCOChartModel * JCOListModel * JCOTableViewModel *

    */public class R3Table extends com.sap.mw.jco.JCO.Table {public static final String READ_TABLE_FUNCTION_NAME = "RFC_READ_TABLE";public static final String DATA_DELIMITER = "|";private long queryDuration = 0;private String tableName = "";private String whereClause = "";private int maxRows = 0;private int skipCount = 0;private HashMap desiredFields = null;

    /** * Private class to track field size and offset. */private class FieldInfo {FieldInfo(String _name, int _offset, int _length, String _type) {this._name = _name;this._endindex = _offset + _length;this._offset = _offset;this._length = _length;this._type = _type;

    }int _endindex;String _name;int _offset;int _length;String _type;

    }

    /** * Method shouldIKeepField. * Determines if the specified field name should be recorded. *

  • * @param fieldName * @return boolean */private boolean shouldIKeepField(String fieldName) {// if null (none specified), we want all fieldsif (desiredFields == null)return true;

    // if we have a list and the field name is there.if (desiredFields.containsKey(fieldName.toUpperCase()))return true;

    return false;}

    /** * Method getFieldInfo. * @param table */private void getFieldInfo(JCO.Table table) {table.firstRow();HashMap fieldList = new HashMap(table.getNumColumns());

    do {String fn = table.getField("FIELDNAME").getString().toUpperCase();if (shouldIKeepField(fn)) {FieldInfo fi = new FieldInfo(table.getField("FIELDNAME").getString(),

    table.getField("OFFSET").getInt(), table.getField("LENGTH").getInt(), table.getField("TYPE").getString());

    fieldList.put(fn,fi);}

    } while(table.nextRow());

    desiredFields = fieldList;}

    /** * Method recordDesiredFields. * Records the desired field names that should come back from the RFC call. * @param fieldList */private void recordDesiredFields(String fieldList) {StringTokenizer st = new StringTokenizer(fieldList,", ");if (st.hasMoreTokens()) {desiredFields = new HashMap();while (st.hasMoreTokens()) {String fn = st.nextToken().toUpperCase();if (!desiredFields.containsKey(fn))desiredFields.put(fn, null);

    }}

    }

    /** * Method processRows. * Loops through the raw JCO.Table rows and parses the field values into their * corresponding fields in the current table. *

    * @param table * @throws Exception */private void processRows(JCO.Table table) throws JCO.Exception {Object[] fieldList = desiredFields.values().toArray();for (int i=0; i < table.getNumRows();i++) {table.setRow(i);String row = table.getField("WA").getString();appendRow();

    for (int f=0;f row.length())endIndex = row.length();

    String val = row.substring(fi._offset, endIndex);setValue(val.trim(), fi._name);

    }}

  • }/** * Private Constructor, use static method R3Table.getInstance to * create an instance of this class. *

    * @see com.sap.mw.jco.JCO.MetaData#MetaData(IMetaData) */private R3Table(IMetaData imd) {super(imd);

    }

    /** * Returns a string representation of the object, * which is a result of R3Table info + a call to JCO.Table.toString(). * * * Fetch Function: RFC_READ_TABLE * Where Clause: * Max Rows: 5 * Delimiter: | * Query Response Time (ms): 172 * Skip Count: 4 * Fields: LAND1, NATIO, MANDT, LANDX, SPRAS * -------------------------------------

    * | TABLE 'T005T' * -------------------------------------

    * | MA| | LA| LANDX | NATIO | * -------------------------------------

    * |012|3|456|789012345678901|234567890123456| * -------------------------------------

    * |151|1|AI |Anguilla |Anguilla | * |151|1|AL |Albania |Albanian | * |151|1|AM |Armenia |Armenian | * |151|1|AN |Dutch Antilles |Dutch | * |151|1|AO |Angola |Angolan | * -------------------------------------

    * *

    * @see java.lang.Object#toString() */public String toString() {

    StringBuffer retStr = new StringBuffer();

    retStr.append("Fetch Function: " + READ_TABLE_FUNCTION_NAME + "\n");retStr.append("Where Clause: " + whereClause + "\n");retStr.append("Max Rows: " + (maxRows >0 ? "" + maxRows : "All") + "\n" );retStr.append("Delimiter: " + DATA_DELIMITER + "\n" );retStr.append("Query Response Time (ms): " + queryDuration + "\n");retStr.append("Skip Count: " + skipCount + "\n");retStr.append("Fields: ");if (desiredFields != null) {for (Iterator i = desiredFields.keySet().iterator() ; i.hasNext() ;) {

    retStr.append(i.next()); if (i.hasNext()) retStr.append(", ");

    } }else {retStr.append("ALL");

    }retStr.append("\n");

    return retStr.toString() + super.toString();

    }

    /** * Method executeQuery. * Connects to the R/3 system associated with client and fetches the raw table data. * @param repository * @param client * @throws R3TableException * @throws Exception */private void executeQuery(IRepository repository, JCO.Client client) throws

    R3TableException, JCO.Exception {IFunctionTemplate rfc = null;JCO.Table rawData = null;

  • JCO.Table fieldData = null;JCO.Table options = null;

    rfc = repository.getFunctionTemplate(READ_TABLE_FUNCTION_NAME);JCO.Function function = new JCO.Function(rfc);JCO.ParameterList importList = function.getImportParameterList();

    importList.setValue(tableName, "QUERY_TABLE");importList.setValue(DATA_DELIMITER, "DELIMITER");importList.setValue(" ", "NO_DATA");

    if (maxRows > 0)importList.setValue(maxRows, "ROWCOUNT");

    if (skipCount > 0)importList.setValue(skipCount, "ROWSKIPS");

    if (whereClause.length() > 0) {options = function.getTableParameterList().getTable("OPTIONS");options.appendRow();options.setValue(whereClause, "TEXT");

    }

    client.execute(function);rawData = function.getTableParameterList().getTable("DATA");fieldData = function.getTableParameterList().getTable("FIELDS");getFieldInfo(fieldData);

    processRows(rawData);}

    /** * Method getInstance - Short Form. Instantiates an R3Table class populated with thedata selected from the specified table. * Returns ALL rows, ALL fields, without skipping. * @param client An already connected JCO.Client. * @param tableName SAP Table to query. *

    * *For example, to load ALL rows and fields from SAP Table T502T * *...

    *client = clientService.getJCOClient("SAP_HR_SYS", request); *client.connect(); *R3Table table = R3Table.getInstance(client, "T502T"); *...

    * * *

    *

    * @return R3Table *

    * @throws R3TableException * @throws com.sap.mw.jco.JCO.Exception */public static R3Table getInstance(JCO.Client client, String tableName) throws

    R3TableException, JCO.Exception {return getInstance(client, tableName, "", "", 0, 0);

    }

    /** * Method getInstance - Medium Form. Instantiates an R3Table class populated with thedata selected from the specified table. * Returns ALL rows, ALL fields, without skipping. * @param client An already connected JCO.Client. * @param tableName ABAP Table to query. * @param whereClause ABAP WHERE CLAUSE such as SPRAS = 'Q' OR SPRAS = 'T'

    * @return R3Table *

    * @throws R3TableException * @throws com.sap.mw.jco.JCO.Exception */public static R3Table getInstance(JCO.Client client, String tableName, String

    whereClause) throws R3TableException, JCO.Exception {return getInstance(client, tableName, whereClause, "", 0, 0);

    }

  • /** * Method getInstance - Medium Form. Instantiates an R3Table class populated with thedata selected from the specified table. * Returns ALL rows, without skipping. * @param client An already connected JCO.Client. * @param tableName ABAP Table to query. * @param whereClause ABAP WHERE CLAUSE such as SPRAS = 'Q' OR SPRAS = 'T' * @param desiredFields A List of Field Names delimited by commas. An empty Stringindicates ALL fields.

    * @return R3Table *

    * @throws R3TableException * @throws com.sap.mw.jco.JCO.Exception */public static R3Table getInstance(JCO.Client client, String tableName, String

    whereClause, String desiredFields) throws R3TableException, JCO.Exception {return getInstance(client, tableName, whereClause, desiredFields, 0, 0);

    }

    /** * Method getInstance - Long Form. Instantiates an R3Table class populated with the dataselected from the specified table. * Returns specified number of rows, without skipping. * @param client An already connected JCO.Client. * @param tableName ABAP Table to query. * @param whereClause ABAP WHERE CLAUSE such as SPRAS = 'Q' OR SPRAS = 'T' * @param desiredFields A List of Field Names delimited by commas. An empty Stringindicates ALL fields. * @param maxRows The maximum number of row to return.

    * @return R3Table *

    * @throws R3TableException * @throws com.sap.mw.jco.JCO.Exception */public static R3Table getInstance(JCO.Client client, String tableName, String

    whereClause, String desiredFields, int maxRows) throws R3TableException, JCO.Exception {return getInstance(client, tableName, whereClause, desiredFields, 0, maxRows);

    }

    /** * Method getInstance - Long Form. Instantiates an R3Table class populated with the dataselected from the specified table. * @param client An already connected JCO.Client. * @param tableName ABAP Table to query. * @param whereClause ABAP WHERE CLAUSE such as SPRAS = 'Q' OR SPRAS = 'T' * @param desiredFields A List of Field Names delimited by commas. An empty Stringindicates ALL fields. * @param skipCount The number of rows to skip. 0 indicates no skipping. * @param maxRows The maximum number of row to return.

    * @return R3Table *

    * @throws R3TableException * @throws com.sap.mw.jco.JCO.Exception */public static R3Table getInstance(JCO.Client client, String tableName, String

    whereClause, String desiredFields, int skipCount, int maxRows) throws R3TableException,JCO.Exception {

    R3Table retTable;IRepository repository = JCO.createRepository("repository." + client.toString(),

    client);retTable = new R3Table(repository.getTableDefinition(tableName));retTable.setMaxRows(maxRows);retTable.setWhereClause(whereClause);retTable.setTableName(tableName);retTable.recordDesiredFields(desiredFields);retTable.setSkipCount(skipCount);long st = System.currentTimeMillis();retTable.executeQuery(repository, client);long et = System.currentTimeMillis();retTable.setQueryDuration(et - st);

    return retTable;}

  • // ************* Private setters ***************private void setMaxRows(int maxRows) {this.maxRows = maxRows;

    }

    private void setQueryDuration(long queryDuration) {this.queryDuration = queryDuration;

    }

    private void setTableName(String tableName) {this.tableName = tableName;

    }

    private void setWhereClause(String whereClause) {this.whereClause = whereClause;

    }

    private void setSkipCount(int skipCount) {this.skipCount = skipCount;

    }

    }

  • demoBean.javapackage com.colpal.demo.R3Table;

    import com.sapportals.htmlb.IListModel;import com.sapportals.htmlb.table.JCOTableViewModel;import com.colpal.util.portal.*;import com.sap.mw.jco.JCO;import java.io.Serializable;public class demoBean implements Serializable {private JCOTableViewModel tableListModel = null;private R3Table table = null;private boolean error = false;private String lastMessage = "";private boolean bHasData = false;

    public boolean isError() {return error;

    }

    public boolean hasData() {return bHasData;

    }

    public void loadTable(JCO.Client client, String tableName) {setLastMessage("");error = false;try {table = R3Table.getInstance(client, tableName);bHasData = true;

    }catch (Exception e) {setLastMessage(e.getMessage());error = true;

    }}

    /** * Returns the tableListModel. * @return TableViewModel */public JCOTableViewModel getTableListModel() {return new JCOTableViewModel(table);

    }

    /** * Sets the tableListModel */public void setTableListModel(JCOTableViewModel employmentListModel) {this.tableListModel = employmentListModel;

    }

    /** * Returns the lastMessage. * @return String */public String getLastMessage() {return lastMessage;

    }

    /** * Sets the lastMessage. * @param lastMessage The lastMessage to set */public void setLastMessage(String lastMessage) {this.lastMessage = lastMessage;

    }

    }page1.jsp

  • AppController.javapackage com.colpal.demo.R3Table;

    import com.colpal.demo.R3Table.demoBean;import com.sapportals.htmlb.*;import com.sapportals.htmlb.enum.*;import com.sapportals.htmlb.event.*;import com.sapportals.htmlb.page.*;import com.sapportals.portal.htmlb.page.*;import com.sapportals.portal.prt.component.*;import com.sapportals.portal.prt.service.jco.IJCOClientService;import com.colpal.util.portal.*;

    import com.sap.mw.jco.JCO;import com.sap.mw.jco.IFunctionTemplate;import com.sap.mw.jco.IRepository;import com.sap.mw.jco.*;public class AppController extends PageProcessorComponent {

    public DynPage getPage(){ return new AppControllerDynPage(); }

    public static class AppControllerDynPage extends JSPDynPage{

    private demoBean myBean = null;

    public void getBeanFromFramework() {IPortalComponentSession componentSession =

    ((IPortalComponentRequest)getRequest()).getComponentSession();Object o = componentSession.getValue("myBean");if(o==null || !(o instanceof demoBean)){myBean = new demoBean();componentSession.putValue("myBean",myBean);

    } else {

    myBean = (demoBean) o; }}

    public void doInitialization() { getBeanFromFramework();

    }

    public void onLoadTable(Event event) {

    IPortalComponentRequest request = (IPortalComponentRequest) this.getRequest();JCO.Client client = null;IJCOClientService clientService = (IJCOClientService)

    request.getService(IJCOClientService.KEY);

    getBeanFromFramework();String tableName = null;

    Component component = getComponentByName("tableName");if (component != null)if (component instanceof InputField)tableName = ((InputField)component).getValueAsDataType().toString();

    if (tableName != null) {try {client = clientService.getJCOClient("SAP_GHD_151", request); client.connect();myBean.loadTable(client,tableName.toUpperCase());

    }catch (Exception e) {e.printStackTrace();

    }

    finally {if (client != null)client.disconnect();

    }

    }

  • } public void doProcessAfterInput() throws PageException { }

    public void doProcessBeforeOutput() throws PageException {this.setJspName("page1.jsp");

    } }}