├── .abapgit.xml ├── LICENSE ├── LICENSES └── Apache-2.0.txt ├── README.md ├── REUSE.toml ├── images ├── 010_select_function_modules.png ├── 020_specify_options.png ├── 030_result_report.png ├── 040_generated_objects.png └── README.md └── src ├── package.devc.xml ├── zcl_gen_rfc_tier2_proxy.clas.abap ├── zcl_gen_rfc_tier2_proxy.clas.xml ├── zr_gen_rfc_tier2_proxy.prog.abap └── zr_gen_rfc_tier2_proxy.prog.xml /.abapgit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TEST_AF_TIER2_RFC_PROXY (report and class) 6 | E 7 | /src/ 8 | PREFIX 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSES/Apache-2.0.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![REUSE status](https://api.reuse.software/badge/github.com/SAP-samples/tier2-rfc-proxy)](https://api.reuse.software/info/github.com/SAP-samples/tier2-rfc-proxy) 2 | 3 | # Tier2 RFC proxy generator 4 | 5 | ## Description 6 | 7 | This repository contains a helper class and a report that helps you to generate a custom wrapper for the ABAP Cloud enablement of an non-released RFC based SAP API. 8 | 9 | It basically uses the same API used by transaction ACO_PROXY. It takes the code that is generated by this API and creates an interface and a factory class and C1-releases those objects. So it basically automates most of the steps described in this repository [RAP640 - Using ABAP Cloud to Build Extensions for SAP S/4HANA Cloud, Private Edition - Mitigating Missing Released SAP APIs in the 3-tier Extensibility Model](https://github.com/SAP-samples/abap-platform-rap640/tree/main). 10 | 11 | The transaction ACO_PROXY and its underlying API now also check if a data element that is used by a non released function module itself has been released. If this is the case, no shadow type will be generated. 12 | 13 | ## Blog Post in SAP Community 14 | 15 | [Blog Post: How to generate a wrapper for function modules (BAPIs) in tier 2](https://community.sap.com/t5/technology-blogs-by-sap/how-to-generate-a-wrapper-for-function-modules-bapis-in-tier-2/ba-p/13692790) 16 | 17 | ## Requirements 18 | 19 | - You have to have a system based on SAP S/4HANA 2022 on premise. 20 | - You have to have enabled Developer extensibility 21 | - You have to apply the following notes 22 | - [SAP Note 3444292 - ACO Proxy creates unnecessary shadow types](https://me.sap.com/notes/3444292) 23 | - [SAP Note 3457580 - SAP ACO - Duplicate Types for Table Parameters](https://me.sap.com/notes/3457580) 24 | 25 | 26 | ## Future Outlook 27 | In future the idea is to provide such a generator as well in the ABAP development tools for Eclipse. 28 | This will be possible with the next S/4HANA release and the ADT generator framework.     29 | 30 | ## How to section 31 | 32 | The tool can be used in short as follows: 33 | 34 | 1. Start report **zr_gen_rfc_tier2_proxy** using transaction **SE38**. 35 | 2. Select one or more function modules that shall be wrapped for the use in ABAP Cloud. 36 | 37 | Select function modules 38 | 39 | 3. Select remaining parameters 40 | 41 | Select remaining parameters 42 | 43 | 3.1 **Target Package** : Here you have to select the package in which the wrapper objects shall be generated 44 | 45 | 3.2 **Intf., class and fact.class**: When you select this option the generator will generate a wrapper class, an interface and a factory class (this is recommended) 46 | **Only wrapper class**: When you select this option the generator will only generate a wrapper class, for those that do not want to generate 3 wrapper objects 47 | 3.3 Here you have to specify the repository object names that shall be generated. Depending on the option you have chosen you have to specify the names of three objects or just for one class. 48 | 3.4 You can specify whether the objects if they already exist are being overwritten 49 | 50 | 5. Start the report and check the output. 51 | 52 | Check output of report 53 | 54 | 6. Check the generated objects in the target package. 55 | 56 | Check generated objects 57 | 58 | 7. What is now left to do is that the developer has to implement the public methods with a call of the respective private methods. 59 | 60 | Here it is possible to change the signature of the public method e.g. by reducing the number of parameters that are exposed. 61 | 62 | By default the public and private methods use the same signature. 63 | 64 | ```ABAP 65 | METHOD zif_wrap_test_003~bapi_pr_create. 66 | "add call to private method bapi_pr_create 67 | "e.g. me->bapi_pr_create( ... ) 68 | ENDMETHOD. 69 | ``` 70 | 71 | ## Generated code 72 | 73 | ### Wrapper Interface 74 | 75 | ```ABAP 76 | INTERFACE zif_wrap_test_003 77 | PUBLIC . 78 | 79 | TYPES: 80 | banfn TYPE c LENGTH 000010 ##TYPSHADOW . 81 | TYPES: 82 | bsart TYPE c LENGTH 000004 ##TYPSHADOW . 83 | TYPES: 84 | bsakz TYPE c LENGTH 000001 ##TYPSHADOW . 85 | TYPES: 86 | gsfrg TYPE c LENGTH 000001 ##TYPSHADOW . 87 | TYPES: 88 | estkz TYPE c LENGTH 000001 ##TYPSHADOW . 89 | 90 | .... 91 | 92 | TYPES: 93 | BEGIN OF bapimereqheader , 94 | preq_no TYPE banfn, 95 | pr_type TYPE bsart, 96 | ctrl_ind TYPE bsakz, 97 | general_release TYPE gsfrg, 98 | create_ind TYPE estkz, 99 | item_intvl TYPE pincr, 100 | last_item TYPE lponr, 101 | auto_source TYPE kzzuo, 102 | memory TYPE membf, 103 | hold_complete TYPE bapimereqpostflag, 104 | hold_uncomplete TYPE bapimereqpostflag, 105 | park_complete TYPE bapimereqpostflag, 106 | park_uncomplete TYPE bapimereqpostflag, 107 | memorytype TYPE memorytype, 108 | END OF bapimereqheader ##TYPSHADOW . 109 | TYPES: 110 | BEGIN OF bapimereqheaderx , 111 | preq_no TYPE bapiupdate, 112 | 113 | ... 114 | 115 | METHODS bapi_pr_create 116 | IMPORTING 117 | !prheader TYPE bapimereqheader OPTIONAL 118 | !prheaderx TYPE bapimereqheaderx OPTIONAL 119 | !testrun TYPE char1 OPTIONAL 120 | !_dest_ TYPE rfcdest DEFAULT 'NONE' 121 | EXPORTING 122 | !number TYPE banfn 123 | !prheaderexp TYPE bapimereqheader 124 | CHANGING 125 | !allversions TYPE _bapimedcm_allversions OPTIONAL 126 | !extensionin TYPE _bapiparex OPTIONAL 127 | !extensionout TYPE _bapiparex OPTIONAL 128 | !praccount TYPE _bapimereqaccount OPTIONAL 129 | !praccountproitsegment TYPE _bapimereqaccountprofitseg OPTIONAL 130 | !praccountx TYPE _bapimereqaccountx OPTIONAL 131 | !praddrdelivery TYPE _bapimerqaddrdelivery OPTIONAL 132 | !prcomponents TYPE _bapimereqcomponent OPTIONAL 133 | !prcomponentsx TYPE _bapimereqcomponentx OPTIONAL 134 | !prheadertext TYPE _bapimereqheadtext OPTIONAL 135 | !pritem TYPE _bapimereqitemimp 136 | !pritemexp TYPE _bapimereqitem OPTIONAL 137 | !pritemsource TYPE _bapimereqsource OPTIONAL 138 | !pritemtext TYPE _bapimereqitemtext OPTIONAL 139 | !pritemx TYPE _bapimereqitemx OPTIONAL 140 | !prversion TYPE _bapimereqdcm OPTIONAL 141 | !prversionx TYPE _bapimereqdcmx OPTIONAL 142 | !return TYPE _bapiret2 OPTIONAL 143 | !serialnumber TYPE _bapimereqserialno OPTIONAL 144 | !serialnumberx TYPE _bapimereqserialnox OPTIONAL 145 | !serviceaccount TYPE _bapi_srv_acc_data OPTIONAL 146 | !serviceaccountx TYPE _bapi_srv_acc_datax OPTIONAL 147 | !servicecontractlimits TYPE _bapi_srv_contract_limits OPTIONAL 148 | !servicecontractlimitsx TYPE _bapi_srv_contract_limitsx OPTIONAL 149 | !servicelimit TYPE _bapi_srv_limit_data OPTIONAL 150 | !servicelimitx TYPE _bapi_srv_limit_datax OPTIONAL 151 | !servicelines TYPE _bapi_srv_service_line OPTIONAL 152 | !servicelinesx TYPE _bapi_srv_service_linex OPTIONAL 153 | !servicelongtexts TYPE _bapi_srv_longtexts OPTIONAL 154 | !serviceoutline TYPE _bapi_srv_outline OPTIONAL 155 | !serviceoutlinex TYPE _bapi_srv_outlinex OPTIONAL 156 | RAISING 157 | cx_aco_application_exception 158 | cx_aco_communication_failure 159 | cx_aco_system_failure . 160 | ENDINTERFACE. 161 | 162 | ``` 163 | 164 | ### Wrapper Class 165 | 166 | ```ABAP 167 | CLASS zcl_wrap_test_003 DEFINITION 168 | PUBLIC 169 | FINAL 170 | CREATE PUBLIC . 171 | PUBLIC SECTION. 172 | INTERFACES zif_wrap_test_003. 173 | PROTECTED SECTION. 174 | PRIVATE SECTION. 175 | 176 | METHODS bapi_pr_create 177 | IMPORTING 178 | !prheader TYPE zif_wrap_test_003~bapimereqheader OPTIONAL 179 | !prheaderx TYPE zif_wrap_test_003~bapimereqheaderx OPTIONAL 180 | !testrun TYPE zif_wrap_test_003~char1 OPTIONAL 181 | !_dest_ TYPE rfcdest DEFAULT 'NONE' 182 | EXPORTING 183 | !number TYPE zif_wrap_test_003~banfn 184 | !prheaderexp TYPE zif_wrap_test_003~bapimereqheader 185 | 186 | ... 187 | 188 | ... 189 | 190 | CLASS zcl_wrap_test_003 IMPLEMENTATION. 191 | 192 | METHOD bapi_pr_create. 193 | DATA: _rfc_message_ TYPE aco_proxy_msg_type. 194 | CALL FUNCTION 'BAPI_PR_CREATE' DESTINATION space 195 | EXPORTING 196 | prheader = prheader 197 | prheaderx = prheaderx 198 | testrun = testrun 199 | IMPORTING 200 | number = number 201 | prheaderexp = prheaderexp 202 | TABLES 203 | allversions = allversions 204 | extensionin = extensionin 205 | extensionout = extensionout 206 | praccount = praccount 207 | ... 208 | serviceoutlinex = serviceoutlinex 209 | EXCEPTIONS 210 | communication_failure = 1 MESSAGE _rfc_message_ 211 | system_failure = 2 MESSAGE _rfc_message_ 212 | OTHERS = 3. 213 | IF sy-subrc NE 0. 214 | DATA __sysubrc TYPE sy-subrc. 215 | DATA __textid TYPE aco_proxy_textid_type. 216 | __sysubrc = sy-subrc. 217 | __textid-msgid = sy-msgid. 218 | __textid-msgno = sy-msgno. 219 | __textid-attr1 = sy-msgv1. 220 | __textid-attr2 = sy-msgv2. 221 | __textid-attr3 = sy-msgv3. 222 | __textid-attr4 = sy-msgv4. 223 | CASE __sysubrc. 224 | WHEN 1 . 225 | RAISE EXCEPTION TYPE cx_aco_communication_failure 226 | EXPORTING 227 | rfc_msg = _rfc_message_. 228 | WHEN 2 . 229 | RAISE EXCEPTION TYPE cx_aco_system_failure 230 | EXPORTING 231 | rfc_msg = _rfc_message_. 232 | WHEN 3 . 233 | RAISE EXCEPTION TYPE cx_aco_application_exception 234 | EXPORTING 235 | exception_id = 'OTHERS' 236 | textid = __textid. 237 | ENDCASE. 238 | ENDIF. 239 | 240 | ENDMETHOD. 241 | 242 | 243 | METHOD zif_wrap_test_003~bapi_pr_create. 244 | "add call to private method bapi_pr_create 245 | "e.g. me->bapi_pr_create( ... ) 246 | ENDMETHOD. 247 | ENDCLASS. 248 | 249 | ``` 250 | 251 | ### Factory Class 252 | 253 | ```ABAP 254 | CLASS zcl_fact_test_003 DEFINITION 255 | PUBLIC 256 | FINAL 257 | CREATE PRIVATE . 258 | PUBLIC SECTION. 259 | CLASS-METHODS create_instance 260 | RETURNING VALUE(result) TYPE REF TO zif_wrap_test_003. 261 | PROTECTED SECTION. 262 | PRIVATE SECTION. 263 | METHODS constructor. 264 | ENDCLASS. 265 | 266 | CLASS zcl_fact_test_003 IMPLEMENTATION. 267 | METHOD constructor. 268 | ENDMETHOD. 269 | METHOD create_instance. 270 | result = NEW zcl_wrap_test_003( ). 271 | ENDMETHOD. 272 | ENDCLASS. 273 | ``` 274 | 275 | 276 | ## Background 277 | 278 | This report uses under the hood the API's that are used by transaction **ACO_PROXY**. 279 | 280 | In principle you can achieve the same result by running the transaction ACO_PROXY which will generated a wrapper class and then perform the following steps: 281 | 282 | - create an interface 283 | - copy the code of the definition part of the class generated by ACO_PROXY to the interface 284 | - replace the CLASS-METHODS statements with METHODS statements in the interface 285 | - replace the defintion part of the wrapper class generated by ACO_PROXY with an INTERFACE statement 286 | - change the __dest__ statements with _space_ statements. 287 | - create a factory class that instantiates the wrapper class 288 | - C1 release the interface and the factory class 289 | 290 | 291 | 292 | ## Further information 293 | 294 | - [ABAP Cloud - How to mitigate missing released SAP APIs in SAP S/4HANA Cloud, private edition and SAP S/4HANA – The new ABAP Cloud API enablement guide](https://community.sap.com/t5/enterprise-resource-planning-blogs-by-sap/abap-cloud-how-to-mitigate-missing-released-sap-apis-in-sap-s-4hana-cloud/ba-p/13561479) 295 | 296 | - [ABAP Cloud – Mitigate missing released SAP APIs in the 3-tier extensibility model: a tutorial how to wrap a BAPI and integrate it into a custom RAP business object](https://community.sap.com/t5/enterprise-resource-planning-blogs-by-sap/abap-cloud-mitigate-missing-released-sap-apis-in-the-3-tier-extensibility/ba-p/13580268) 297 | 298 | 299 | 300 | ## Download and Installation 301 | 302 | ## Known Issues 303 | No known issues. 304 | 305 | ## How to obtain support 306 | [Create an issue](https://github.com/SAP-samples/tier2-rfc-proxy/issues) in this repository if you find a bug or have questions about the content. 307 | 308 | For additional support, [ask a question in SAP Community](https://answers.sap.com/questions/ask.html). 309 | 310 | ## Contributing 311 | If you wish to contribute code, offer fixes or improvements, please send a pull request. Due to legal reasons, contributors will be asked to accept a DCO when they create the first pull request to this project. This happens in an automated fashion during the submission process. SAP uses [the standard DCO text of the Linux Foundation](https://developercertificate.org/). 312 | 313 | ## License 314 | Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved. This project is licensed under the Apache Software License, version 2.0 except as noted otherwise in the [LICENSE](LICENSE) file. 315 | -------------------------------------------------------------------------------- /REUSE.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | SPDX-PackageName = "sap-samples/tier2-rfc-proxy" 3 | SPDX-PackageSupplier = "andre.fischer@sap.com" 4 | SPDX-PackageDownloadLocation = "https://github.com/sap-samples/tier2-rfc-proxy" 5 | SPDX-PackageComment = "The code in this project may include calls to APIs (\"API Calls\") of\n SAP or third-party products or services developed outside of this project\n (\"External Products\").\n \"APIs\" means application programming interfaces, as well as their respective\n specifications and implementing code that allows software to communicate with\n other software.\n API Calls to External Products are not licensed under the open source license\n that governs this project. The use of such API Calls and related External\n Products are subject to applicable additional agreements with the relevant\n provider of the External Products. In no event shall the open source license\n that governs this project grant any rights in or to any External Products,or\n alter, expand or supersede any terms of the applicable additional agreements.\n If you have a valid license agreement with SAP for the use of a particular SAP\n External Product, then you may make use of any API Calls included in this\n project's code for that SAP External Product, subject to the terms of such\n license agreement. If you do not have a valid license agreement for the use of\n a particular SAP External Product, then you may only make use of any API Calls\n in this project for that SAP External Product for your internal, non-productive\n and non-commercial test and evaluation of such API Calls. Nothing herein grants\n you any rights to use or access any SAP External Product, or provide any third\n parties the right to use of access any SAP External Product, through API Calls." 6 | 7 | [[annotations]] 8 | path = "**" 9 | precedence = "aggregate" 10 | SPDX-FileCopyrightText = " SAP SE or an SAP affiliate company and contributors" 11 | SPDX-License-Identifier = "Apache-2.0" 12 | 13 | [[annotations]] 14 | path = "" 15 | precedence = "aggregate" 16 | SPDX-FileCopyrightText = "" 17 | SPDX-License-Identifier = "" 18 | 19 | [[annotations]] 20 | path = "" 21 | precedence = "aggregate" 22 | SPDX-FileCopyrightText = "" 23 | SPDX-License-Identifier = "" 24 | -------------------------------------------------------------------------------- /images/010_select_function_modules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/tier2-rfc-proxy/a7157e822a66090414a09d15f4c6c492394ceadf/images/010_select_function_modules.png -------------------------------------------------------------------------------- /images/020_specify_options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/tier2-rfc-proxy/a7157e822a66090414a09d15f4c6c492394ceadf/images/020_specify_options.png -------------------------------------------------------------------------------- /images/030_result_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/tier2-rfc-proxy/a7157e822a66090414a09d15f4c6c492394ceadf/images/030_result_report.png -------------------------------------------------------------------------------- /images/040_generated_objects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-samples/tier2-rfc-proxy/a7157e822a66090414a09d15f4c6c492394ceadf/images/040_generated_objects.png -------------------------------------------------------------------------------- /images/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/package.devc.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | TEST_AF_TIER2_RFC_PROXY 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/zcl_gen_rfc_tier2_proxy.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_gen_rfc_tier2_proxy DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. 7 | 8 | DATA function_modules TYPE cl_aco_metadata_provider=>t_functions READ-ONLY. 9 | DATA function_module TYPE cl_aco_metadata_provider=>t_function READ-ONLY. 10 | 11 | DATA wrapper_class_name TYPE sxco_class_name READ-ONLY. 12 | DATA wrapper_interface_name TYPE sxco_class_name READ-ONLY. 13 | DATA wrapper_factory_class_name TYPE sxco_class_name READ-ONLY. 14 | 15 | DATA package_name TYPE sxco_package READ-ONLY. 16 | 17 | DATA namespace TYPE string READ-ONLY. 18 | 19 | DATA transport_request TYPE sxco_transport READ-ONLY. 20 | 21 | DATA wrapper_interface_code TYPE rswsourcet READ-ONLY. 22 | DATA wrapper_class_code TYPE rswsourcet READ-ONLY. 23 | DATA wrapper_factory_class_code TYPE rswsourcet READ-ONLY. 24 | 25 | DATA methods_code_definition TYPE rswsourcet READ-ONLY . 26 | DATA methods_code_implementation TYPE rswsourcet READ-ONLY. 27 | 28 | INTERFACES if_oo_adt_classrun . 29 | 30 | 31 | METHODS constructor 32 | IMPORTING 33 | i_package_name TYPE sxco_package 34 | i_transport_request TYPE sxco_transport OPTIONAL 35 | i_generate_intf_and_fact_class TYPE abap_bool DEFAULT abap_true 36 | i_wrapper_class_name TYPE sxco_class_name 37 | i_wrapper_interface_name TYPE sxco_class_name OPTIONAL 38 | i_wrapper_factory_class_name TYPE sxco_class_name OPTIONAL 39 | i_function_modules TYPE cl_aco_metadata_provider=>t_functions 40 | i_overwrite_objects TYPE abap_bool DEFAULT abap_true 41 | RAISING cx_abap_invalid_value. 42 | 43 | 44 | METHODS read_aco_proxy_cls_src_code 45 | * IMPORTING remove_class_method_statements TYPE abap_bool DEFAULT abap_true 46 | RETURNING VALUE(aco_proxy_class_src_code) TYPE rswsourcet. 47 | 48 | METHODS get_wrapper_class_code 49 | IMPORTING I_aco_proxy_class_src_code TYPE rswsourcet 50 | RETURNING VALUE(r_wrapper_class_code) TYPE rswsourcet.. 51 | 52 | METHODS get_wrapper_interface_code 53 | IMPORTING I_aco_proxy_class_src_code TYPE rswsourcet 54 | RETURNING VALUE(r_wrapper_interface_code) TYPE rswsourcet. 55 | 56 | METHODS get_private_methods_code 57 | IMPORTING I_aco_proxy_class_src_code TYPE rswsourcet 58 | EXPORTING 59 | r_methods_definition_code TYPE rswsourcet 60 | r_methods_implementation_code TYPE rswsourcet. 61 | 62 | METHODS get_wrapper_factory_class_code 63 | RETURNING VALUE(r_wrapper__factory_class_code) TYPE rswsourcet.. 64 | 65 | METHODS generate_wrapper_objects 66 | IMPORTING i_demo_mode TYPE abap_bool DEFAULT abap_false 67 | RETURNING VALUE(r_exception_text) TYPE string. 68 | 69 | METHODS generate_wrapper_interface. 70 | 71 | METHODS generate_factory_class. 72 | 73 | METHODS update_wrapper_objects_code 74 | IMPORTING 75 | i_object_type TYPE trobjtype 76 | i_object_name TYPE trobj_name 77 | i_source_code TYPE rswsourcet. 78 | 79 | 80 | METHODS generate_aco_proxy_class 81 | IMPORTING 82 | i_function_modules TYPE cl_aco_metadata_provider=>t_functions 83 | I_proxy_class_name TYPE sxco_class_name 84 | i_package_name TYPE sxco_package 85 | i_transport_request TYPE sxco_transport 86 | RETURNING VALUE(success) TYPE abap_bool 87 | RAISING cx_aco_exception. 88 | 89 | 90 | METHODS get_namespace 91 | IMPORTING i_package_name TYPE string 92 | RETURNING VALUE(r_namespace) TYPE string. 93 | 94 | 95 | METHODS get_unique_object_name 96 | IMPORTING i_short_object_name TYPE sxco_class_name 97 | * i_namespace TYPE string 98 | i_object_type TYPE trobjtype 99 | RETURNING VALUE(r_object_name) TYPE sxco_class_name. 100 | 101 | 102 | METHODS release_class_and_interface 103 | RAISING cx_abap_api_state. 104 | 105 | METHODS create_transport RETURNING VALUE(r_transport) TYPE sxco_transport. 106 | 107 | PROTECTED SECTION. 108 | PRIVATE SECTION. 109 | 110 | DATA generate_intf_and_fact_class TYPE abap_bool. 111 | DATA overwrite_objects TYPE abap_bool. 112 | 113 | 114 | ENDCLASS. 115 | 116 | 117 | 118 | CLASS zcl_gen_rfc_tier2_proxy IMPLEMENTATION. 119 | 120 | METHOD constructor. 121 | 122 | IF NOT xco_abap_repository=>object->devc->for( i_package_name )->exists( ). 123 | RAISE EXCEPTION TYPE cx_abap_invalid_value EXPORTING value = | package { i_package_name } does not exist |. 124 | ENDIF. 125 | 126 | package_name = i_package_name . 127 | namespace = get_namespace( CONV #( package_name ) ). 128 | 129 | IF i_transport_request IS INITIAL. 130 | "create transport checks if the selected package records changes 131 | transport_request = create_transport( ) . 132 | ELSE. 133 | transport_request = i_transport_request . 134 | ENDIF. 135 | 136 | generate_intf_and_fact_class = i_generate_intf_and_fact_class. 137 | 138 | overwrite_objects = i_overwrite_objects. 139 | 140 | IF i_overwrite_objects = abap_false. 141 | IF i_generate_intf_and_fact_class = abap_true. 142 | IF xco_abap_repository=>object->clas->for( i_wrapper_class_name )->exists( ). 143 | RAISE EXCEPTION TYPE cx_abap_invalid_value EXPORTING value = | Class { i_wrapper_class_name } does already exist |. 144 | ELSEIF xco_abap_repository=>object->intf->for( i_wrapper_interface_name )->exists( ). 145 | RAISE EXCEPTION TYPE cx_abap_invalid_value EXPORTING value = | Interface { i_wrapper_interface_name } does already exist |. 146 | ELSEIF xco_abap_repository=>object->clas->for( i_wrapper_factory_class_name )->exists( ). 147 | RAISE EXCEPTION TYPE cx_abap_invalid_value EXPORTING value = | Class { i_wrapper_factory_class_name } does already exist |. 148 | ENDIF. 149 | ELSE. 150 | IF xco_abap_repository=>object->clas->for( i_wrapper_class_name )->exists( ). 151 | RAISE EXCEPTION TYPE cx_abap_invalid_value EXPORTING value = | Class { i_wrapper_class_name } does already exist |. 152 | ENDIF. 153 | ENDIF. 154 | ENDIF. 155 | 156 | wrapper_class_name = i_wrapper_class_name . 157 | wrapper_interface_name = i_wrapper_interface_name . 158 | wrapper_factory_class_name = i_wrapper_factory_class_name . 159 | 160 | LOOP AT i_function_modules INTO DATA(function_module). 161 | 162 | SELECT SINGLE * FROM tfdir INTO @DATA(function_module_info) WHERE funcname = @function_module-functionname. 163 | 164 | IF function_module_info IS INITIAL. 165 | RAISE EXCEPTION TYPE cx_abap_invalid_value EXPORTING value = | Function module { function_module-functionname } does not exist.|. 166 | ENDIF. 167 | 168 | IF function_module_info-fmode IS NOT INITIAL. 169 | APPEND function_module TO function_modules. 170 | ELSE. 171 | RAISE EXCEPTION TYPE cx_abap_invalid_value EXPORTING value = | Function module { function_module-functionname } is not remote enabled.|. 172 | ENDIF. 173 | 174 | ENDLOOP. 175 | 176 | ENDMETHOD. 177 | 178 | METHOD generate_wrapper_objects. 179 | TRY. 180 | generate_aco_proxy_class( 181 | i_function_modules = function_modules 182 | i_proxy_class_name = wrapper_class_name 183 | i_package_name = package_name 184 | i_transport_request = transport_request 185 | ). 186 | CATCH cx_aco_exception INTO DATA(aco_exception). 187 | r_exception_text = |ACO error: { aco_exception->get_text( ) }|. 188 | RETURN. 189 | ENDTRY. 190 | 191 | read_aco_proxy_cls_src_code( 192 | * EXPORTING 193 | * remove_class_method_statements = abap_true 194 | RECEIVING 195 | aco_proxy_class_src_code = DATA(aco_proxy_class_code) 196 | ). 197 | 198 | IF aco_proxy_class_code IS INITIAL. 199 | r_exception_text = |No source code found: { wrapper_class_name }|. 200 | RETURN. 201 | ENDIF. 202 | 203 | 204 | IF generate_intf_and_fact_class = abap_true. 205 | 206 | get_wrapper_interface_code( 207 | EXPORTING 208 | i_aco_proxy_class_src_code = aco_proxy_class_code 209 | RECEIVING 210 | r_wrapper_interface_code = wrapper_interface_code 211 | ). 212 | 213 | get_private_methods_code( 214 | EXPORTING 215 | i_aco_proxy_class_src_code = aco_proxy_class_code 216 | IMPORTING 217 | r_methods_definition_code = methods_code_definition 218 | r_methods_implementation_code = methods_code_implementation 219 | ). 220 | 221 | get_wrapper_factory_class_code( 222 | RECEIVING 223 | r_wrapper__factory_class_code = wrapper_factory_class_code 224 | ). 225 | 226 | ENDIF. 227 | 228 | get_wrapper_class_code( 229 | EXPORTING 230 | i_aco_proxy_class_src_code = aco_proxy_class_code 231 | RECEIVING 232 | r_wrapper_class_code = wrapper_class_code 233 | ). 234 | 235 | IF i_demo_mode = abap_false. 236 | 237 | TRY. 238 | 239 | IF generate_intf_and_fact_class = abap_true. 240 | 241 | IF xco_abap_repository=>object->intf->for( wrapper_interface_name )->exists( ) = abap_False. 242 | generate_wrapper_interface( ). 243 | ELSE. 244 | ASSERT overwrite_objects = abap_true. 245 | ENDIF. 246 | 247 | IF xco_abap_repository=>object->clas->for( wrapper_factory_class_name )->exists( ) = abap_False. 248 | generate_factory_class( ). 249 | ELSE. 250 | ASSERT overwrite_objects = abap_true. 251 | ENDIF. 252 | 253 | update_wrapper_objects_code( 254 | i_object_type = 'INTF' 255 | i_object_name = CONV #( wrapper_interface_name ) 256 | i_source_code = wrapper_interface_code 257 | ). 258 | 259 | ENDIF. 260 | 261 | update_wrapper_objects_code( 262 | i_object_type = 'CLAS' 263 | i_object_name = CONV #( wrapper_class_name ) 264 | i_source_code = wrapper_class_code 265 | ). 266 | 267 | IF generate_intf_and_fact_class = abap_true. 268 | 269 | update_wrapper_objects_code( 270 | i_object_type = 'CLAS' 271 | i_object_name = CONV #( wrapper_factory_class_name ) 272 | i_source_code = wrapper_factory_class_code 273 | ). 274 | 275 | ENDIF. 276 | 277 | CATCH cx_oo_class_scan_error INTO DATA(update_wrapper_code_exc). 278 | r_exception_text = |cl_oo_factory error: { update_wrapper_code_exc->get_text( ) }|. 279 | RETURN. 280 | ENDTRY. 281 | 282 | TRY. 283 | release_class_and_interface( ). 284 | CATCH cx_abap_api_state INTO DATA(api_state_exception). 285 | r_exception_text = |api_state error: { api_state_exception->get_text( ) }|. 286 | RETURN. 287 | ENDTRY. 288 | 289 | ENDIF. 290 | 291 | ENDMETHOD. 292 | 293 | METHOD if_oo_adt_classrun~main. 294 | 295 | package_name = 'TEST_AF_GENERATED_OBJECTS_001'. 296 | transport_request = ''. 297 | 298 | DATA number TYPE i VALUE 106. 299 | 300 | DATA(project_name) = 'af_wrapper_t'. 301 | 302 | function_module-functionname = to_upper( 'bapi_epm_product_get_detail' ). 303 | APPEND function_module TO function_modules. 304 | function_module-functionname = to_upper( 'bapi_epm_product_get_list' ). 305 | APPEND function_module TO function_modules. 306 | 307 | wrapper_class_name = to_upper( namespace && 'cl_wrap_' && project_name ). 308 | wrapper_interface_name = to_upper( namespace && 'if_wrap_' && project_name ). 309 | wrapper_factory_class_name = to_upper( namespace && 'cl_fact_' && project_name ) . 310 | 311 | 312 | wrapper_class_name = get_unique_object_name( 313 | i_short_object_name = wrapper_class_name 314 | i_object_type = 'CLAS' 315 | ). 316 | 317 | wrapper_interface_name = get_unique_object_name( 318 | i_short_object_name = wrapper_interface_name 319 | i_object_type = 'INTF' 320 | ) . 321 | wrapper_factory_class_name = get_unique_object_name( 322 | i_short_object_name = wrapper_factory_class_name 323 | i_object_type = 'CLAS' 324 | ). 325 | 326 | out->write( wrapper_class_name ). 327 | out->write( wrapper_interface_name ). 328 | out->write( wrapper_factory_class_name ). 329 | 330 | out->write( 'finished' ). 331 | 332 | ENDMETHOD. 333 | 334 | METHOD generate_aco_proxy_class. 335 | 336 | cl_aco_static_proxy=>create_static_proxy_by_rfc( 337 | EXPORTING 338 | function_names = i_function_modules 339 | proxy_name = i_proxy_class_name 340 | destination_name = 'NONE' 341 | devclass = i_package_name 342 | trkorr = i_transport_request 343 | classic_exceptions = abap_false 344 | bapi_exceptions = abap_false 345 | generate_inactive = abap_false 346 | destination_by_constructor = abap_false 347 | do_not_create_released_type = abap_true 348 | ). 349 | success = abap_true. 350 | 351 | ENDMETHOD. 352 | 353 | METHOD read_aco_proxy_cls_src_code. 354 | 355 | FIELD-SYMBOLS TYPE string. 356 | 357 | SELECT SINGLE * FROM i_abapobjectdirectoryentry INTO @DATA(obj_entry) 358 | WHERE abapobject = @wrapper_class_name 359 | . 360 | 361 | DATA(package) = obj_entry-abappackage. 362 | 363 | IF package IS INITIAL. 364 | EXIT. 365 | ENDIF. 366 | 367 | "read source code of generated proxy class 368 | DATA(ref_proxy_class_name) = cl_oo_factory=>create_instance( )->create_clif_source( to_upper( wrapper_class_name ) ). 369 | ref_proxy_class_name->get_source( IMPORTING source = aco_proxy_class_src_code ). 370 | 371 | ENDMETHOD. 372 | 373 | METHOD get_wrapper_factory_class_code. 374 | 375 | 376 | APPEND |CLASS { wrapper_factory_class_name } DEFINITION | TO r_wrapper__factory_class_code. 377 | APPEND |PUBLIC | TO r_wrapper__factory_class_code. 378 | APPEND |FINAL | TO r_wrapper__factory_class_code. 379 | APPEND |CREATE PRIVATE . | TO r_wrapper__factory_class_code. 380 | 381 | APPEND | PUBLIC SECTION. | TO r_wrapper__factory_class_code. 382 | 383 | 384 | APPEND | CLASS-METHODS create_instance | TO r_wrapper__factory_class_code. 385 | APPEND | RETURNING VALUE(result) TYPE REF TO { wrapper_interface_name }. | TO r_wrapper__factory_class_code. 386 | APPEND | PROTECTED SECTION. | TO r_wrapper__factory_class_code. 387 | APPEND | PRIVATE SECTION. | TO r_wrapper__factory_class_code. 388 | APPEND | METHODS constructor. | TO r_wrapper__factory_class_code. 389 | APPEND |ENDCLASS. | TO r_wrapper__factory_class_code. 390 | 391 | APPEND | CLASS { wrapper_factory_class_name } IMPLEMENTATION. | TO r_wrapper__factory_class_code. 392 | 393 | APPEND | METHOD create_instance. | TO r_wrapper__factory_class_code. 394 | 395 | APPEND | result = NEW { wrapper_class_name }( ). | TO r_wrapper__factory_class_code. 396 | APPEND | ENDMETHOD.| TO r_wrapper__factory_class_code. 397 | 398 | APPEND | METHOD constructor. | TO r_wrapper__factory_class_code. 399 | APPEND | ENDMETHOD. | TO r_wrapper__factory_class_code. 400 | 401 | APPEND | ENDCLASS. | TO r_wrapper__factory_class_code. 402 | 403 | 404 | ENDMETHOD. 405 | 406 | METHOD get_wrapper_interface_code. 407 | 408 | DATA add_code TYPE abap_bool. 409 | DATA source_code_line LIKE LINE OF i_aco_proxy_class_src_code. 410 | 411 | APPEND |INTERFACE { wrapper_interface_name }| TO r_wrapper_interface_code. 412 | APPEND | PUBLIC . | TO r_wrapper_interface_code. 413 | 414 | LOOP AT i_aco_proxy_class_src_code INTO source_code_line. 415 | 416 | DATA(result_last_statement) = find( val = source_code_line sub = |PROTECTED SECTION.| case = abap_false ). 417 | DATA(result_first_statement) = find( val = source_code_line sub = |INTERFACES if_aco_proxy| case = abap_false ). 418 | DATA(result_class_methods) = find( val = source_code_line sub = |CLASS-METHODS| case = abap_false ). 419 | DATA(result_if_aco_proxy) = find( val = source_code_line sub = |if_aco_proxy| case = abap_false ). 420 | 421 | IF result_class_methods <> -1. 422 | source_code_line = replace( val = source_code_line 423 | sub = |CLASS-METHODS| 424 | with = |METHODS| ). 425 | ENDIF. 426 | 427 | 428 | IF result_first_statement <> -1. 429 | add_code = abap_true. 430 | ENDIF. 431 | 432 | IF result_last_statement <> -1. 433 | APPEND |ENDINTERFACE.| TO r_wrapper_interface_code. 434 | EXIT. 435 | ENDIF. 436 | 437 | "skip if_aco_proxy statement 438 | IF add_code = abap_true AND result_if_aco_proxy = -1. 439 | APPEND source_code_line TO r_wrapper_interface_code. 440 | ENDIF. 441 | 442 | ENDLOOP. 443 | ENDMETHOD. 444 | 445 | METHOD get_wrapper_class_code. 446 | 447 | DATA add_code TYPE abap_bool. 448 | DATA source_code_line LIKE LINE OF i_aco_proxy_class_src_code. 449 | 450 | IF generate_intf_and_fact_class = abap_false. 451 | 452 | LOOP AT i_aco_proxy_class_src_code INTO source_code_line. 453 | 454 | " add a final statement before the CREATE PUBLIC statement. 455 | DATA(result_create_public_statement) = find( val = source_code_line sub = |CREATE PUBLIC| case = abap_false ). 456 | DATA(result_if_aco_proxy) = find( val = source_code_line sub = |if_aco_proxy| case = abap_false ). 457 | 458 | IF result_create_public_statement <> -1. 459 | APPEND 'FINAL' TO r_wrapper_class_code. 460 | source_code_line = replace( val = source_code_line 461 | sub = |CREATE PUBLIC| 462 | with = |CREATE PRIVATE| ). 463 | ENDIF. 464 | 465 | "remove DESTINATION _dest_ statements 466 | DATA(result_destination_statement) = find( val = source_code_line sub = |DESTINATION _dest_| case = abap_false ). 467 | * source_code_line = to_upper( source_code_line ). 468 | IF result_destination_statement <> -1. 469 | source_code_line = replace( val = source_code_line 470 | sub = |DESTINATION _dest_| 471 | with = |DESTINATION space| ). 472 | ENDIF. 473 | IF result_if_aco_proxy = -1. 474 | APPEND source_code_line TO r_wrapper_class_code. 475 | ENDIF. 476 | ENDLOOP. 477 | 478 | RETURN. 479 | 480 | ENDIF. 481 | 482 | CLEAR r_wrapper_class_code. 483 | 484 | APPEND |CLASS { wrapper_class_name } DEFINITION| TO r_wrapper_class_code. 485 | APPEND |PUBLIC | TO r_wrapper_class_code. 486 | APPEND |FINAL | TO r_wrapper_class_code. 487 | APPEND |CREATE PUBLIC . | TO r_wrapper_class_code. 488 | APPEND |PUBLIC SECTION. | TO r_wrapper_class_code. 489 | APPEND |INTERFACES { wrapper_interface_name }.| TO r_wrapper_class_code. 490 | APPEND |PROTECTED SECTION. | TO r_wrapper_class_code. 491 | APPEND |PRIVATE SECTION. | TO r_wrapper_class_code. 492 | 493 | "add private methods code 494 | 495 | LOOP AT methods_code_definition INTO DATA(method_code_line). 496 | APPEND method_code_line TO r_wrapper_class_code. 497 | ENDLOOP. 498 | APPEND |.| TO r_wrapper_class_code. 499 | APPEND |ENDCLASS.| TO r_wrapper_class_code. 500 | APPEND | | TO r_wrapper_class_code. 501 | 502 | LOOP AT i_aco_proxy_class_src_code INTO source_code_line. 503 | 504 | DATA(result_method_statement) = find( val = source_code_line sub = |METHOD| case = abap_false ). 505 | DATA(result_first_statement) = find( val = source_code_line sub = |CLASS { wrapper_class_name } IMPLEMENTATION.| case = abap_false ). 506 | 507 | "remove DESTINATION _dest_ 508 | result_destination_statement = find( val = source_code_line sub = |DESTINATION _dest_| case = abap_false ). 509 | 510 | IF result_first_statement <> -1. 511 | add_code = abap_true. 512 | ENDIF. 513 | 514 | "add interface name to method name 515 | * IF result_method_statement <> -1 . 516 | * source_code_line = to_upper( source_code_line ). 517 | * source_code_line = replace( val = source_code_line 518 | * sub = |METHOD | 519 | * with = |METHOD { wrapper_interface_name }~| ). 520 | * ENDIF. 521 | 522 | IF result_destination_statement <> -1. 523 | source_code_line = replace( val = source_code_line 524 | sub = |DESTINATION _dest_| 525 | with = |DESTINATION space| ). 526 | ENDIF. 527 | 528 | IF add_code = abap_true. 529 | APPEND source_code_line TO r_wrapper_class_code. 530 | IF result_first_statement <> -1. 531 | LOOP AT methods_code_implementation INTO DATA(methods_code_impl_line). 532 | APPEND methods_code_impl_line TO r_wrapper_class_code. 533 | ENDLOOP. 534 | ENDIF. 535 | ENDIF. 536 | ENDLOOP. 537 | 538 | 539 | ENDMETHOD. 540 | 541 | METHOD update_wrapper_objects_code. 542 | 543 | DATA(ref) = cl_oo_factory=>create_instance( )->create_clif_source( to_upper( i_object_name ) ). 544 | 545 | TRY. 546 | ref->lock( ). 547 | ref->set_source( source = i_source_code ). 548 | ref->save( ). 549 | ref->unlock( ). 550 | CATCH cx_oo_access_permission cx_oo_class_scan_error INTO DATA(access_permission_exc). 551 | * WRITE : / |error occured: { access_permission_exc->get_text( ) }|. 552 | * EXIT. 553 | ENDTRY. 554 | 555 | * DATA objects TYPE STANDARD TABLE OF dwinactiv . 556 | * 557 | * objects = VALUE #( ( object = i_object_type obj_name = i_object_name uname = sy-uname ) ). 558 | * 559 | * CALL FUNCTION 'RS_WORKING_OBJECTS_ACTIVATE' 560 | * TABLES 561 | * objects = objects 562 | * EXCEPTIONS 563 | * excecution_error = 1 564 | * cancelled = 2 565 | * insert_into_corr_error = 3 566 | * OTHERS = 4. 567 | 568 | IF sy-subrc <> 0. 569 | * WRITE : / |error occured when activating class { cls_name }. SY-SUBRC = { sy-subrc } |. 570 | * EXIT. 571 | ENDIF. 572 | ENDMETHOD. 573 | 574 | 575 | 576 | METHOD generate_wrapper_interface. 577 | 578 | DATA lo_put_operation TYPE REF TO if_xco_gen_intf_o_put . 579 | 580 | IF transport_request IS INITIAL. 581 | lo_put_operation = xco_generation=>environment->local->for-intf->create_put_operation( ). 582 | ELSE. 583 | lo_put_operation = xco_generation=>environment->transported( transport_request )->for-intf->create_put_operation( ). 584 | ENDIF. 585 | 586 | DATA(lo_form_specification) = lo_put_operation->add_object( wrapper_interface_name 587 | )->set_package( package_name 588 | )->create_form_specification( ). 589 | 590 | lo_form_specification->set_short_description( 'Sample interface' ) ##NO_TEXT. 591 | 592 | 593 | lo_put_operation->execute( ). 594 | 595 | ENDMETHOD. 596 | 597 | METHOD generate_factory_class. 598 | 599 | DATA lo_put_operation TYPE REF TO if_xco_gen_clas_o_put . 600 | 601 | IF transport_request IS INITIAL. 602 | lo_put_operation = xco_generation=>environment->local->for-clas->create_put_operation( ). 603 | ELSE. 604 | lo_put_operation = xco_generation=>environment->transported( transport_request )->for-clas->create_put_operation( ). 605 | ENDIF. 606 | 607 | DATA(lo_form_specification) = lo_put_operation->add_object( wrapper_factory_class_name 608 | )->set_package( package_name 609 | )->create_form_specification( ). 610 | 611 | lo_form_specification->set_short_description( 'Factory class' ) ##NO_TEXT. 612 | 613 | 614 | lo_put_operation->execute( ). 615 | ENDMETHOD. 616 | 617 | METHOD get_namespace. 618 | 619 | IF i_package_name = '$TMP'. 620 | r_namespace = 'Z'. 621 | EXIT. 622 | ENDIF. 623 | 624 | FIND ALL OCCURRENCES OF '/' 625 | IN i_package_name 626 | IGNORING CASE " case insensitive 627 | RESULTS DATA(result). " TYPE match_result_tab 628 | 629 | IF lines( result ) = 2. 630 | CHECK result[ 1 ]-offset = 0. 631 | r_namespace = substring( val = i_package_name len = result[ 2 ]-offset + 1 ). 632 | EXIT. 633 | ENDIF. 634 | 635 | DATA(first_character_package) = substring( val = i_package_name off = 0 len = 1 ). 636 | DATA(package_name_length) = strlen( i_package_name ). 637 | 638 | IF first_character_package = 'Y'. 639 | r_namespace = 'Y'. 640 | EXIT. 641 | ENDIF. 642 | 643 | IF first_character_package = 'Z'. 644 | r_namespace = 'Z'. 645 | EXIT. 646 | ENDIF. 647 | 648 | IF package_name_length > strlen( 'TEST_' ). 649 | IF substring( val = i_package_name len = strlen( 'TEST_' ) ) = 'TEST_' . 650 | r_namespace = 'Z'. 651 | EXIT. 652 | ENDIF. 653 | ENDIF. 654 | 655 | r_namespace = ''. 656 | 657 | 658 | ENDMETHOD. 659 | 660 | METHOD get_unique_object_name. 661 | 662 | DATA is_valid_repo_object_name TYPE abap_bool VALUE abap_false. 663 | DATA unique_number TYPE i VALUE 0. 664 | DATA unique_hex_number TYPE xstring . 665 | DATA unique_hex_number_string TYPE c LENGTH 2. 666 | 667 | "Generate a short class name that provides us the option to add two characters to suggest a unique name 668 | * DATA short_class_name TYPE c LENGTH 28. 669 | 670 | * short_class_name = i_namespace && 'CL_WRAP_' && i_fugr_name. 671 | 672 | WHILE is_valid_repo_object_name = abap_false AND unique_number < 255 . 673 | 674 | unique_hex_number = CONV xstring( unique_number ). 675 | 676 | IF unique_hex_number = 00. 677 | unique_hex_number_string = ''. 678 | ELSE. 679 | unique_hex_number_string = unique_hex_number. 680 | ENDIF. 681 | 682 | r_object_name = i_short_object_name && unique_hex_number_string. 683 | 684 | IF i_object_type = 'CLAS'. 685 | IF NOT xco_abap_repository=>object->clas->for( r_object_name )->exists( ). 686 | is_valid_repo_object_name = abap_true. 687 | ELSE. 688 | unique_number += 1. 689 | ENDIF. 690 | ELSEIF i_object_type = 'INTF'. 691 | IF NOT xco_abap_repository=>object->intf->for( r_object_name )->exists( ). 692 | is_valid_repo_object_name = abap_true. 693 | ELSE. 694 | unique_number += 1. 695 | ENDIF. 696 | ELSE. 697 | ASSERT 1 = 0. 698 | ENDIF. 699 | 700 | ENDWHILE. 701 | 702 | ENDMETHOD. 703 | 704 | 705 | 706 | 707 | METHOD release_class_and_interface. 708 | 709 | IF generate_intf_and_fact_class = abap_true. 710 | 711 | DATA(api_state_wrapper_fact_class) = cl_abap_api_state=>create_instance( 712 | api_key = VALUE #( 713 | object_type = 'CLAS' 714 | object_name = to_upper( wrapper_factory_class_name ) 715 | ) ). 716 | 717 | api_state_wrapper_fact_class->release( 718 | EXPORTING 719 | release_contract = 'C1' 720 | use_in_cloud_development = abap_true 721 | use_in_key_user_apps = abap_false 722 | request = transport_request 723 | ). 724 | 725 | 726 | DATA(api_state_wrapper_interface) = cl_abap_api_state=>create_instance( 727 | api_key = VALUE #( 728 | object_type = 'INTF' 729 | object_name = to_upper( wrapper_interface_name ) 730 | ) ). 731 | 732 | api_state_wrapper_interface->release( 733 | EXPORTING 734 | release_contract = 'C1' 735 | use_in_cloud_development = abap_true 736 | use_in_key_user_apps = abap_false 737 | request = transport_request 738 | ). 739 | 740 | ELSE. 741 | DATA(api_state_wrapper_class) = cl_abap_api_state=>create_instance( 742 | api_key = VALUE #( 743 | object_type = 'CLAS' 744 | object_name = to_upper( wrapper_class_name ) 745 | ) ). 746 | 747 | api_state_wrapper_class->release( 748 | EXPORTING 749 | release_contract = 'C1' 750 | use_in_cloud_development = abap_true 751 | use_in_key_user_apps = abap_false 752 | request = transport_request 753 | ). 754 | ENDIF. 755 | 756 | ENDMETHOD. 757 | 758 | METHOD create_transport. 759 | DATA(xco_package) = xco_abap_repository=>object->devc->for( package_name ). 760 | DATA(record_object_changes) = xco_package->read( )-property-record_object_changes. 761 | IF record_object_changes = abap_true. 762 | DATA(lo_transport_target) = xco_package->read( )-property-transport_layer->get_transport_target( ). 763 | DATA(new_transport_object) = xco_cp_cts=>transports->workbench( lo_transport_target->value )->create_request( |Wrapper class: { wrapper_class_name } | ). 764 | r_transport = new_transport_object->value. 765 | ELSE. 766 | r_transport = ''. 767 | ENDIF. 768 | ENDMETHOD. 769 | 770 | METHOD get_private_methods_code. 771 | DATA add_code TYPE abap_bool. 772 | DATA result_in_interface TYPE abap_bool. 773 | 774 | DATA source_code_line LIKE LINE OF i_aco_proxy_class_src_code. 775 | 776 | * APPEND |INTERFACE { wrapper_interface_name }| TO r_methods_definition_code. 777 | * APPEND | PUBLIC . | TO r_wrapper_interface_code. 778 | 779 | LOOP AT i_aco_proxy_class_src_code INTO source_code_line. 780 | 781 | DATA(result_last_statement) = find( val = source_code_line sub = |.| case = abap_false ). 782 | DATA(result_first_statement) = find( val = source_code_line sub = |CLASS-METHODS| case = abap_false ). 783 | DATA(result_type_statement) = find( val = source_code_line sub = |TYPE | case = abap_false ). 784 | DATA(result_endclass_statement) = find( val = source_code_line sub = |ENDCLASS.| case = abap_false ). 785 | 786 | DATA(result_class_methods) = find( val = source_code_line sub = |CLASS-METHODS| case = abap_false ). 787 | 788 | DATA(result_destination_statement) = find( val = source_code_line sub = |_dest_| case = abap_false ). 789 | 790 | DATA(result_none_statement) = find( val = source_code_line sub = |'NONE'| case = abap_false ). 791 | 792 | " !prheader TYPE ZIF_WRAP_TEST_4714~bapimereqheader OPTIONAL 793 | 794 | DATA(result_exclamation_mark) = find( val = source_code_line sub = |!| case = abap_false ). 795 | 796 | 797 | IF result_class_methods <> -1. 798 | source_code_line = replace( val = source_code_line 799 | sub = |CLASS-METHODS| 800 | with = |METHODS| ). 801 | DATA(source_code_line_impl) = replace( val = source_code_line 802 | sub = |METHODS | 803 | with = |METHOD { wrapper_interface_name }~| ). 804 | DATA(method_name) = replace( val = source_code_line 805 | sub = |METHODS | 806 | with = || ). 807 | CONDENSE method_name NO-GAPS. 808 | source_code_line_impl = source_code_line_impl && '.'. 809 | * APPEND |.| TO r_methods_implementation_code. 810 | APPEND source_code_line_impl TO r_methods_implementation_code. 811 | APPEND | "add call to private method { method_name }| TO r_methods_implementation_code. 812 | APPEND | "e.g. me->{ method_name }( ... ) | TO r_methods_implementation_code. 813 | APPEND |RAISE EXCEPTION TYPE cx_method_not_implemented.| TO r_methods_implementation_code. 814 | APPEND |ENDMETHOD.| TO r_methods_implementation_code. 815 | ENDIF. 816 | 817 | IF result_endclass_statement <> -1. 818 | EXIT. 819 | ENDIF. 820 | DATA string1 TYPE string. 821 | DATA string2 TYPE string. 822 | DATA pos TYPE i. 823 | CLEAR pos. 824 | IF result_exclamation_mark <> -1. 825 | 826 | SPLIT source_code_line AT '!' INTO string1 string2. 827 | SPLIT string2 AT space INTO TABLE DATA(source_code_line_tab). 828 | 829 | LOOP AT source_code_line_tab INTO DATA(single_statement). 830 | pos += 1. 831 | IF single_statement = 'TYPE'. 832 | DATA(pos_type) = pos. 833 | ENDIF. 834 | ENDLOOP. 835 | 836 | DATA(type_of) = source_code_line_tab[ pos_type + 1 ]. 837 | 838 | "REPLACE '!' IN type_of WITH ''. 839 | 840 | LOOP AT wrapper_interface_code INTO DATA(interface_code_line). 841 | CLEAR result_in_interface. 842 | DATA(result_is_in_interface) = find( val = interface_code_line sub = type_of case = abap_false ). 843 | DATA(first_methods_statement) = find( val = interface_code_line sub = 'METHODS' case = abap_false ). 844 | "only search in types statements 845 | IF first_methods_statement <> -1. 846 | EXIT. 847 | ENDIF. 848 | IF result_is_in_interface <> -1. 849 | result_in_interface = abap_true. 850 | EXIT. 851 | ENDIF. 852 | ENDLOOP. 853 | ENDIF. 854 | 855 | IF result_first_statement <> -1. 856 | add_code = abap_true. 857 | ENDIF. 858 | 859 | IF add_code = abap_true AND result_last_statement <> -1. 860 | add_code = abap_false. 861 | ENDIF. 862 | 863 | IF result_type_statement <> -1 AND 864 | result_in_interface = abap_true AND 865 | result_destination_statement = -1 866 | . 867 | 868 | "certain function modules such as SATC_CI_GET_RESULT use 869 | "built in types such as 'I' 870 | "searching for 'I' by name is not reliable 871 | 872 | CASE to_upper( type_of ). 873 | "built in numeric types 874 | WHEN 'I' OR 'B' OR 'S' OR 'INT8' OR 'P' OR 'F'. 875 | "built in character type 876 | WHEN 'C' OR 'N' OR 'STRING'. 877 | "built in date type 878 | WHEN 'D' OR 'T'. 879 | "not a built in type 880 | WHEN OTHERS. 881 | source_code_line = replace( val = source_code_line 882 | sub = |TYPE | 883 | with = |TYPE { wrapper_interface_name }~| ). 884 | ENDCASE. 885 | ENDIF. 886 | 887 | IF result_destination_statement <> -1. 888 | source_code_line = replace( val = source_code_line 889 | sub = |DESTINATION _dest_| 890 | with = |DESTINATION space| ). 891 | ENDIF. 892 | 893 | IF result_none_statement <> -1. 894 | source_code_line = replace( val = source_code_line 895 | sub = |DESTINATION 'NONE'| 896 | with = |DESTINATION space| ). 897 | ENDIF. 898 | 899 | IF add_code = abap_true. 900 | 901 | IF result_class_methods <> -1. 902 | APPEND '.' TO r_methods_definition_code. 903 | ENDIF. 904 | APPEND source_code_line TO r_methods_definition_code. 905 | ENDIF. 906 | 907 | 908 | 909 | ENDLOOP. 910 | APPEND '.' TO r_methods_definition_code. 911 | ENDMETHOD. 912 | 913 | ENDCLASS. 914 | -------------------------------------------------------------------------------- /src/zcl_gen_rfc_tier2_proxy.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_GEN_RFC_TIER2_PROXY 7 | E 8 | zcl_gen_rfc_tier2_proxy 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zr_gen_rfc_tier2_proxy.prog.abap: -------------------------------------------------------------------------------- 1 | REPORT zr_gen_rfc_tier2_proxy. 2 | 3 | TYPES: BEGIN OF ty_fugr, 4 | area TYPE tlibg-area, 5 | END OF ty_fugr. 6 | TABLES sscrfields. 7 | DATA function_type TYPE tftit. 8 | DATA function_modules TYPE cl_aco_metadata_provider=>t_functions . 9 | 10 | DATA source_code_line TYPE string. 11 | 12 | SELECT-OPTIONS s_func FOR function_type-funcname NO INTERVALS . 13 | 14 | PARAMETERS package TYPE tadir-devclass. 15 | 16 | PARAMETERS : yes_intf RADIOBUTTON GROUP rad1 DEFAULT 'X', 17 | no_intf RADIOBUTTON GROUP rad1. 18 | 19 | PARAMETERS : wrapclas TYPE sxco_class_name DEFAULT 'ZCL_WRAP_TEST'. 20 | PARAMETERS : wrapfact TYPE sxco_class_name DEFAULT 'ZCL_FACT_TEST'. 21 | PARAMETERS : wrapintf TYPE sxco_class_name DEFAULT 'ZIF_WRAP_TEST'. 22 | 23 | *PARAMETERS : demomode TYPE abap_bool DEFAULT abap_true. 24 | DATA demomode TYPE abap_bool VALUE abap_false. 25 | 26 | "overwrite existing objects 27 | PARAMETERS : patchobj TYPE abap_bool DEFAULT abap_true. 28 | 29 | LOOP AT s_func INTO DATA(function_module_sel_option). 30 | "transaction aco_proxy only supports remote enabled function modules 31 | SELECT SINGLE * FROM tfdir INTO @DATA(function_module_info) WHERE funcname = @function_module_sel_option-low. 32 | IF function_module_info-fmode IS NOT INITIAL. 33 | APPEND to_upper( function_module_sel_option-low ) TO function_modules. 34 | ELSE. 35 | WRITE : / |function module { function_module_sel_option-low } has been skipped, because it is not remote-enabled. |. 36 | ENDIF. 37 | ENDLOOP. 38 | 39 | TRY. 40 | DATA(tier2_rfc_proxy_generator) = NEW zcl_gen_rfc_tier2_proxy( 41 | i_package_name = package 42 | i_transport_request = '' 43 | i_generate_intf_and_fact_class = yes_intf 44 | i_wrapper_class_name = wrapclas 45 | i_wrapper_interface_name = wrapintf 46 | i_wrapper_factory_class_name = wrapfact 47 | i_function_modules = function_modules 48 | i_overwrite_objects = patchobj 49 | ). 50 | 51 | CATCH cx_abap_invalid_value INTO DATA(invalid_parameter). 52 | WRITE : / 'Exception occured:'. 53 | WRITE : / invalid_parameter->get_text( ). 54 | EXIT. 55 | ENDTRY. 56 | 57 | DATA(exception_text) = tier2_rfc_proxy_generator->generate_wrapper_objects( demomode ). 58 | 59 | IF exception_text IS NOT INITIAL. 60 | WRITE : 'Exception occured generating objects:'. 61 | WRITE : exception_text. 62 | EXIT. 63 | ENDIF. 64 | 65 | DATA objects TYPE STANDARD TABLE OF dwinactiv . 66 | 67 | IF yes_intf = abap_true. 68 | objects = VALUE #( 69 | ( object = 'INTF' obj_name = wrapintf uname = sy-uname ) 70 | ( object = 'CLAS' obj_name = wrapclas uname = sy-uname ) 71 | ( object = 'CLAS' obj_name = wrapfact uname = sy-uname ) 72 | ). 73 | ELSE. 74 | objects = VALUE #( 75 | ( object = 'CLAS' obj_name = wrapclas uname = sy-uname ) 76 | ). 77 | ENDIF. 78 | 79 | IF demomode = abap_False. 80 | 81 | CALL FUNCTION 'RS_WORKING_OBJECTS_ACTIVATE' 82 | TABLES 83 | objects = objects 84 | EXCEPTIONS 85 | excecution_error = 1 86 | cancelled = 2 87 | insert_into_corr_error = 3 88 | OTHERS = 4. 89 | 90 | IF sy-subrc <> 0. 91 | WRITE : / |error occured when activating classes. SY-SUBRC = { sy-subrc } |. 92 | EXIT. 93 | ELSE. 94 | WRITE : / |Generation finished:|. 95 | IF yes_intf = abap_true. 96 | WRITE : / |{ wrapclas }, { wrapfact } and { wrapintf }|. 97 | ELSE. 98 | WRITE : / |{ wrapclas }|. 99 | ENDIF. 100 | ENDIF. 101 | 102 | ELSE. 103 | 104 | WRITE : / '***************************'. 105 | WRITE : / 'methods_code_definition'. 106 | WRITE : / '***************************'. 107 | 108 | LOOP AT tier2_rfc_proxy_generator->methods_code_definition INTO source_code_line. 109 | WRITE : / source_code_line. 110 | ENDLOOP. 111 | 112 | WRITE : / '***************************'. 113 | WRITE : / 'methods_code_implementation'. 114 | WRITE : / '***************************'. 115 | 116 | LOOP AT tier2_rfc_proxy_generator->methods_code_implementation INTO source_code_line. 117 | WRITE : / source_code_line. 118 | ENDLOOP. 119 | 120 | WRITE : / '***************************'. 121 | WRITE : / 'wrapper_factory_class_code'. 122 | WRITE : / '***************************'. 123 | 124 | LOOP AT tier2_rfc_proxy_generator->wrapper_factory_class_code INTO source_code_line. 125 | WRITE : / source_code_line. 126 | ENDLOOP. 127 | 128 | WRITE : / '***************************'. 129 | WRITE : / 'wrapper_class_code'. 130 | WRITE : / '***************************'. 131 | 132 | LOOP AT tier2_rfc_proxy_generator->wrapper_class_code INTO source_code_line. 133 | WRITE : / source_code_line. 134 | ENDLOOP. 135 | 136 | WRITE : / '***************************'. 137 | WRITE : / 'wrapper_interface_code'. 138 | WRITE : / '***************************'. 139 | 140 | 141 | LOOP AT tier2_rfc_proxy_generator->wrapper_interface_code INTO source_code_line. 142 | WRITE : / source_code_line. 143 | ENDLOOP. 144 | 145 | ENDIF. 146 | -------------------------------------------------------------------------------- /src/zr_gen_rfc_tier2_proxy.prog.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZR_GEN_RFC_TIER2_PROXY 7 | S 8 | 1 9 | X 10 | D$S 11 | X 12 | 13 | 14 | 15 | R 16 | zr_gen_rfc_tier2_proxy 17 | 22 18 | 19 | 20 | S 21 | DEMOMODE 22 | Demomode 23 | 16 24 | 25 | 26 | S 27 | NO_INTF 28 | Only wrapper class 29 | 26 30 | 31 | 32 | S 33 | PACKAGE 34 | Target Package 35 | 22 36 | 37 | 38 | S 39 | PATCHOBJ 40 | Overwrite objects 41 | 25 42 | 43 | 44 | S 45 | S_FUNC 46 | Function Modules 47 | 24 48 | 49 | 50 | S 51 | WRAPCLAS 52 | Wrapper class 53 | 21 54 | 55 | 56 | S 57 | WRAPFACT 58 | Wrapper factory class 59 | 29 60 | 61 | 62 | S 63 | WRAPINTF 64 | Wrapper interface 65 | 25 66 | 67 | 68 | S 69 | YES_INTF 70 | Intf., class and fact. class 71 | 36 72 | 73 | 74 | 75 | 76 | D 77 | 78 | 79 | S 80 | DEMOMODE 81 | Demomode 82 | 38 83 | 84 | 85 | S 86 | NO_INTF 87 | Nur Wrapper Klasse 88 | 38 89 | 90 | 91 | S 92 | PACKAGE 93 | Zielpaket 94 | 38 95 | 96 | 97 | S 98 | PATCHOBJ 99 | Objekte überschreiben 100 | 38 101 | 102 | 103 | S 104 | S_FUNC 105 | Funktionsbausteine 106 | 38 107 | 108 | 109 | S 110 | WRAPCLAS 111 | Wrapper Klasse 112 | 38 113 | 114 | 115 | S 116 | WRAPFACT 117 | Wrapper Factory Klasse 118 | 38 119 | 120 | 121 | S 122 | WRAPINTF 123 | Wrapper Interface 124 | 38 125 | 126 | 127 | S 128 | YES_INTF 129 | Intf., Klasse u. Fact. Klasse 130 | 38 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | --------------------------------------------------------------------------------