@linkup-ai/abap-ai 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +384 -0
- package/dist/adt-client.js +364 -0
- package/dist/cli/activate.js +113 -0
- package/dist/cli/init.js +333 -0
- package/dist/cli/remove.js +80 -0
- package/dist/cli/status.js +229 -0
- package/dist/cli/systems.js +68 -0
- package/dist/cli.js +81 -0
- package/dist/index.js +1318 -0
- package/dist/knowledge/abap/abap-dictionary.md +199 -0
- package/dist/knowledge/abap/abap-sql.md +296 -0
- package/dist/knowledge/abap/amdp.md +273 -0
- package/dist/knowledge/abap/clean-code.md +293 -0
- package/dist/knowledge/abap/cloud-background-processing.md +250 -0
- package/dist/knowledge/abap/cloud-communication.md +265 -0
- package/dist/knowledge/abap/cloud-development.md +176 -0
- package/dist/knowledge/abap/cloud-extensibility.md +252 -0
- package/dist/knowledge/abap/cloud-released-apis.md +261 -0
- package/dist/knowledge/abap/constructor-expressions.md +289 -0
- package/dist/knowledge/abap/enhancements.md +232 -0
- package/dist/knowledge/abap/exceptions.md +271 -0
- package/dist/knowledge/abap/internal-tables.md +205 -0
- package/dist/knowledge/abap/object-orientation.md +298 -0
- package/dist/knowledge/abap/performance.md +216 -0
- package/dist/knowledge/abap/rap-abstract-entities.md +206 -0
- package/dist/knowledge/abap/rap-business-events.md +216 -0
- package/dist/knowledge/abap/rap-draft.md +191 -0
- package/dist/knowledge/abap/rap-eml.md +453 -0
- package/dist/knowledge/abap/rap-end-to-end.md +486 -0
- package/dist/knowledge/abap/rap-feature-control.md +185 -0
- package/dist/knowledge/abap/rap-numbering.md +280 -0
- package/dist/knowledge/abap/rap-service-exposure.md +163 -0
- package/dist/knowledge/abap/rap-unmanaged.md +468 -0
- package/dist/knowledge/abap/string-processing.md +180 -0
- package/dist/knowledge/abap/unit-testing.md +303 -0
- package/dist/knowledge/abap-cds/access-control.md +241 -0
- package/dist/knowledge/abap-cds/annotations.md +331 -0
- package/dist/knowledge/abap-cds/associations.md +254 -0
- package/dist/knowledge/abap-cds/expressions.md +230 -0
- package/dist/knowledge/abap-cds/functions.md +245 -0
- package/dist/knowledge/abap-cds/metadata-extensions.md +294 -0
- package/dist/knowledge/cap/authentication.md +278 -0
- package/dist/knowledge/cap/cdl-syntax.md +247 -0
- package/dist/knowledge/cap/cql-queries.md +266 -0
- package/dist/knowledge/cap/deployment.md +343 -0
- package/dist/knowledge/cap/event-handlers.md +287 -0
- package/dist/knowledge/cap/fiori-integration.md +303 -0
- package/dist/knowledge/cap/service-definitions.md +287 -0
- package/dist/knowledge/fiori/annotations.md +347 -0
- package/dist/knowledge/fiori/deployment.md +340 -0
- package/dist/knowledge/fiori/fiori-elements.md +332 -0
- package/dist/knowledge/fiori/fiori-side-effects.md +107 -0
- package/dist/knowledge/fiori/fiori-valuelist.md +144 -0
- package/dist/knowledge/fiori/ui5-controllers.md +358 -0
- package/dist/knowledge/fiori/ui5-data-binding.md +311 -0
- package/dist/knowledge/fiori/ui5-fragments-dialogs.md +330 -0
- package/dist/knowledge/fiori/ui5-manifest.md +411 -0
- package/dist/knowledge/fiori/ui5-routing.md +303 -0
- package/dist/knowledge/fiori/ui5-xml-views.md +294 -0
- package/dist/logger.js +114 -0
- package/dist/system-profile.js +207 -0
- package/dist/tools/abap-doc.js +72 -0
- package/dist/tools/abapgit.js +161 -0
- package/dist/tools/activate.js +68 -0
- package/dist/tools/atc-check.js +117 -0
- package/dist/tools/auth-object.js +56 -0
- package/dist/tools/breakpoints.js +76 -0
- package/dist/tools/call-hierarchy.js +84 -0
- package/dist/tools/cds-annotations.js +98 -0
- package/dist/tools/cds-dependencies.js +65 -0
- package/dist/tools/check.js +47 -0
- package/dist/tools/code-completion.js +70 -0
- package/dist/tools/code-coverage.js +111 -0
- package/dist/tools/create-amdp.js +111 -0
- package/dist/tools/create-dcl.js +81 -0
- package/dist/tools/create-transport.js +38 -0
- package/dist/tools/create.js +285 -0
- package/dist/tools/data-preview.js +37 -0
- package/dist/tools/delete.js +45 -0
- package/dist/tools/deploy-bsp.js +298 -0
- package/dist/tools/discovery.js +59 -0
- package/dist/tools/element-info.js +93 -0
- package/dist/tools/enhancements.js +186 -0
- package/dist/tools/extract-method.js +44 -0
- package/dist/tools/function-group.js +59 -0
- package/dist/tools/knowledge.js +275 -0
- package/dist/tools/lock-object.js +75 -0
- package/dist/tools/message-class.js +67 -0
- package/dist/tools/navigate.js +80 -0
- package/dist/tools/number-range.js +57 -0
- package/dist/tools/object-documentation.js +43 -0
- package/dist/tools/object-structure.js +78 -0
- package/dist/tools/object-versions.js +57 -0
- package/dist/tools/package-contents.js +60 -0
- package/dist/tools/pretty-printer.js +35 -0
- package/dist/tools/publish-binding.js +49 -0
- package/dist/tools/quick-fix.js +69 -0
- package/dist/tools/read.js +167 -0
- package/dist/tools/refactor-rename.js +60 -0
- package/dist/tools/release-transport.js +24 -0
- package/dist/tools/released-apis.js +51 -0
- package/dist/tools/repository-tree.js +90 -0
- package/dist/tools/scaffold-rap.js +642 -0
- package/dist/tools/search.js +73 -0
- package/dist/tools/shared/data-format.js +101 -0
- package/dist/tools/sql-console.js +17 -0
- package/dist/tools/system-info.js +270 -0
- package/dist/tools/traces.js +66 -0
- package/dist/tools/transport-contents.js +83 -0
- package/dist/tools/transports.js +67 -0
- package/dist/tools/unit-test.js +135 -0
- package/dist/tools/where-used.js +59 -0
- package/dist/tools/write.js +101 -0
- package/package.json +49 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# ABAP Cloud Background Processing — application jobs, scheduling
|
|
2
|
+
|
|
3
|
+
## Application Job Architecture
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
Job Catalog Entry (developer — defines the job class)
|
|
7
|
+
→ Job Template (developer — defines default parameters)
|
|
8
|
+
→ Job Scheduling (admin — creates schedule in Fiori app)
|
|
9
|
+
→ Job Execution (runtime — framework calls the class)
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Replaces SM36/SM37 and SUBMIT...VIA JOB.
|
|
13
|
+
|
|
14
|
+
## Job Class Definition
|
|
15
|
+
|
|
16
|
+
```abap
|
|
17
|
+
CLASS zcl_order_cleanup_job DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
|
18
|
+
PUBLIC SECTION.
|
|
19
|
+
INTERFACES if_apj_dt_exec_object. " Design-time: parameter catalog
|
|
20
|
+
INTERFACES if_apj_rt_exec_object. " Run-time: execute method
|
|
21
|
+
ENDCLASS.
|
|
22
|
+
|
|
23
|
+
CLASS zcl_order_cleanup_job IMPLEMENTATION.
|
|
24
|
+
|
|
25
|
+
METHOD if_apj_dt_exec_object~get_parameters.
|
|
26
|
+
" Define job parameters (shown in scheduling UI)
|
|
27
|
+
et_parameter_def = VALUE #(
|
|
28
|
+
( selname = 'P_STATUS'
|
|
29
|
+
kind = if_apj_dt_exec_object=>parameter
|
|
30
|
+
datatype = 'C'
|
|
31
|
+
length = 1
|
|
32
|
+
param_text = 'Status to clean up'
|
|
33
|
+
changeable_ind = abap_true )
|
|
34
|
+
( selname = 'P_DAYS'
|
|
35
|
+
kind = if_apj_dt_exec_object=>parameter
|
|
36
|
+
datatype = 'I'
|
|
37
|
+
param_text = 'Older than (days)'
|
|
38
|
+
changeable_ind = abap_true )
|
|
39
|
+
).
|
|
40
|
+
|
|
41
|
+
" Default values
|
|
42
|
+
et_parameter_val = VALUE #(
|
|
43
|
+
( selname = 'P_STATUS' sign = 'I' option = 'EQ' low = 'D' )
|
|
44
|
+
( selname = 'P_DAYS' sign = 'I' option = 'EQ' low = '30' )
|
|
45
|
+
).
|
|
46
|
+
ENDMETHOD.
|
|
47
|
+
|
|
48
|
+
METHOD if_apj_rt_exec_object~execute.
|
|
49
|
+
" Read parameters
|
|
50
|
+
DATA lv_status TYPE c LENGTH 1.
|
|
51
|
+
DATA lv_days TYPE i.
|
|
52
|
+
|
|
53
|
+
LOOP AT it_parameters INTO DATA(ls_param).
|
|
54
|
+
CASE ls_param-selname.
|
|
55
|
+
WHEN 'P_STATUS'. lv_status = ls_param-low.
|
|
56
|
+
WHEN 'P_DAYS'. lv_days = CONV i( ls_param-low ).
|
|
57
|
+
ENDCASE.
|
|
58
|
+
ENDLOOP.
|
|
59
|
+
|
|
60
|
+
" Calculate cutoff date
|
|
61
|
+
DATA(lv_cutoff) = cl_abap_context_info=>get_system_date( ) - lv_days.
|
|
62
|
+
|
|
63
|
+
" Business logic
|
|
64
|
+
DELETE FROM ztab_order
|
|
65
|
+
WHERE status = @lv_status
|
|
66
|
+
AND created_at < @lv_cutoff.
|
|
67
|
+
|
|
68
|
+
DATA(lv_deleted) = sy-dbcnt.
|
|
69
|
+
|
|
70
|
+
" Log result (application log)
|
|
71
|
+
DATA(lo_log) = cl_bali_log=>create_with_header(
|
|
72
|
+
cl_bali_header_setter=>create(
|
|
73
|
+
iv_object = 'ZORDER' iv_subobject = 'CLEANUP' ) ).
|
|
74
|
+
|
|
75
|
+
lo_log->add_item( cl_bali_message_setter=>create(
|
|
76
|
+
iv_severity = if_bali_constants=>c_severity_information
|
|
77
|
+
iv_message_text = |Deleted { lv_deleted } orders with status { lv_status } older than { lv_days } days| ) ).
|
|
78
|
+
|
|
79
|
+
cl_bali_log_db=>get_instance( )->save_log( lo_log ).
|
|
80
|
+
ENDMETHOD.
|
|
81
|
+
|
|
82
|
+
ENDCLASS.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Job Catalog Entry (ADT)
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
Object type: Application Job Catalog Entry
|
|
89
|
+
Name: Z_JC_ORDER_CLEANUP
|
|
90
|
+
Class: ZCL_ORDER_CLEANUP_JOB
|
|
91
|
+
Description: Clean up old orders
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Created in ADT: New → Other ABAP Repository Object → Application Job Catalog Entry.
|
|
95
|
+
|
|
96
|
+
## Job Template (ADT)
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
Object type: Application Job Template
|
|
100
|
+
Name: Z_JT_ORDER_CLEANUP
|
|
101
|
+
Catalog Entry: Z_JC_ORDER_CLEANUP
|
|
102
|
+
Description: Order cleanup - draft orders 30 days
|
|
103
|
+
Parameters:
|
|
104
|
+
P_STATUS = 'D'
|
|
105
|
+
P_DAYS = '30'
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Schedule Job Programmatically
|
|
109
|
+
|
|
110
|
+
```abap
|
|
111
|
+
" Schedule a job to run immediately
|
|
112
|
+
DATA(lv_job_name) = 'Z_ORDER_CLEANUP_' && sy-datum.
|
|
113
|
+
|
|
114
|
+
cl_apj_rt_api=>schedule_job(
|
|
115
|
+
EXPORTING
|
|
116
|
+
iv_catalog_entry = 'Z_JC_ORDER_CLEANUP'
|
|
117
|
+
iv_template = 'Z_JT_ORDER_CLEANUP'
|
|
118
|
+
iv_job_name = CONV #( lv_job_name )
|
|
119
|
+
it_job_parameter = VALUE #(
|
|
120
|
+
( selname = 'P_STATUS' sign = 'I' option = 'EQ' low = 'X' )
|
|
121
|
+
( selname = 'P_DAYS' sign = 'I' option = 'EQ' low = '7' ) )
|
|
122
|
+
iv_start_info = VALUE cl_apj_rt_api=>ty_start_info(
|
|
123
|
+
start_immediately = abap_true )
|
|
124
|
+
IMPORTING
|
|
125
|
+
ev_jobcount = DATA(lv_jobcount)
|
|
126
|
+
ev_jobname = DATA(lv_jobname) ).
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Schedule Recurring Job
|
|
130
|
+
|
|
131
|
+
```abap
|
|
132
|
+
" Every day at 02:00
|
|
133
|
+
cl_apj_rt_api=>schedule_job(
|
|
134
|
+
EXPORTING
|
|
135
|
+
iv_catalog_entry = 'Z_JC_ORDER_CLEANUP'
|
|
136
|
+
iv_template = 'Z_JT_ORDER_CLEANUP'
|
|
137
|
+
iv_job_name = 'Z_DAILY_CLEANUP'
|
|
138
|
+
iv_start_info = VALUE cl_apj_rt_api=>ty_start_info(
|
|
139
|
+
start_immediately = abap_false
|
|
140
|
+
timestamp = CONV #( '20260315020000' ) )
|
|
141
|
+
iv_scheduling_info = VALUE cl_apj_rt_api=>ty_scheduling_info(
|
|
142
|
+
periodic = abap_true
|
|
143
|
+
period_unit = 'DAY'
|
|
144
|
+
period_value = 1 )
|
|
145
|
+
IMPORTING
|
|
146
|
+
ev_jobcount = DATA(lv_jc)
|
|
147
|
+
ev_jobname = DATA(lv_jn) ).
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Period Units
|
|
151
|
+
|
|
152
|
+
| Unit | Description |
|
|
153
|
+
|------|-------------|
|
|
154
|
+
| `'MIN'` | Minutes |
|
|
155
|
+
| `'HOR'` | Hours |
|
|
156
|
+
| `'DAY'` | Days |
|
|
157
|
+
| `'WEK'` | Weeks |
|
|
158
|
+
| `'MON'` | Months |
|
|
159
|
+
|
|
160
|
+
## Check Job Status
|
|
161
|
+
|
|
162
|
+
```abap
|
|
163
|
+
" Get job status
|
|
164
|
+
cl_apj_rt_api=>get_job_status(
|
|
165
|
+
EXPORTING
|
|
166
|
+
iv_jobname = lv_jobname
|
|
167
|
+
iv_jobcount = lv_jobcount
|
|
168
|
+
IMPORTING
|
|
169
|
+
ev_status = DATA(lv_status)
|
|
170
|
+
ev_status_text = DATA(lv_status_text) ).
|
|
171
|
+
|
|
172
|
+
" Status values:
|
|
173
|
+
" F = Finished
|
|
174
|
+
" A = Aborted
|
|
175
|
+
" R = Running
|
|
176
|
+
" S = Scheduled
|
|
177
|
+
" P = Ready (planned)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Cancel Job
|
|
181
|
+
|
|
182
|
+
```abap
|
|
183
|
+
cl_apj_rt_api=>cancel_job(
|
|
184
|
+
iv_jobname = lv_jobname
|
|
185
|
+
iv_jobcount = lv_jobcount ).
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Using in RAP — Trigger Job from Action
|
|
189
|
+
|
|
190
|
+
```abap
|
|
191
|
+
METHOD scheduleCleanup.
|
|
192
|
+
" RAP action handler that schedules background processing
|
|
193
|
+
TRY.
|
|
194
|
+
cl_apj_rt_api=>schedule_job(
|
|
195
|
+
EXPORTING
|
|
196
|
+
iv_catalog_entry = 'Z_JC_ORDER_CLEANUP'
|
|
197
|
+
iv_template = 'Z_JT_ORDER_CLEANUP'
|
|
198
|
+
iv_job_name = |CLEANUP_{ sy-datum }_{ sy-uzeit }|
|
|
199
|
+
it_job_parameter = VALUE #(
|
|
200
|
+
( selname = 'P_STATUS' sign = 'I' option = 'EQ' low = 'D' )
|
|
201
|
+
( selname = 'P_DAYS' sign = 'I' option = 'EQ' low = '30' ) )
|
|
202
|
+
iv_start_info = VALUE cl_apj_rt_api=>ty_start_info(
|
|
203
|
+
start_immediately = abap_true )
|
|
204
|
+
IMPORTING
|
|
205
|
+
ev_jobname = DATA(lv_job) ).
|
|
206
|
+
|
|
207
|
+
APPEND VALUE #(
|
|
208
|
+
%tky = keys[ 1 ]-%tky
|
|
209
|
+
%msg = new_message_with_text(
|
|
210
|
+
severity = if_abap_behv_message=>severity-success
|
|
211
|
+
text = |Cleanup job { lv_job } scheduled| ) )
|
|
212
|
+
TO reported-order.
|
|
213
|
+
|
|
214
|
+
CATCH cx_apj_rt INTO DATA(lx).
|
|
215
|
+
APPEND VALUE #(
|
|
216
|
+
%tky = keys[ 1 ]-%tky
|
|
217
|
+
%msg = new_message_with_text(
|
|
218
|
+
severity = if_abap_behv_message=>severity-error
|
|
219
|
+
text = lx->get_text( ) ) )
|
|
220
|
+
TO reported-order.
|
|
221
|
+
ENDTRY.
|
|
222
|
+
ENDMETHOD.
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Fiori App — Job Scheduling
|
|
226
|
+
|
|
227
|
+
Admin schedules jobs via Fiori app **Application Jobs** (F1609):
|
|
228
|
+
- Select job template
|
|
229
|
+
- Set parameters
|
|
230
|
+
- Choose schedule (immediate / recurring / calendar)
|
|
231
|
+
- Monitor execution and logs
|
|
232
|
+
|
|
233
|
+
## Rules
|
|
234
|
+
- Job class implements BOTH `if_apj_dt_exec_object` (params) AND `if_apj_rt_exec_object` (execute)
|
|
235
|
+
- Job Catalog Entry + Job Template are design-time artifacts (created in ADT)
|
|
236
|
+
- Job Scheduling is runtime (admin via Fiori app or `cl_apj_rt_api`)
|
|
237
|
+
- Use application logging (`cl_bali_log`) inside jobs for monitoring
|
|
238
|
+
- `cl_abap_context_info=>get_system_date()` instead of `sy-datum` in jobs
|
|
239
|
+
- Parameters use SELECT-OPTIONS structure: selname, sign, option, low, high
|
|
240
|
+
- Handle `cx_apj_rt` when scheduling programmatically
|
|
241
|
+
|
|
242
|
+
## Anti-Patterns
|
|
243
|
+
| Anti-Pattern | Correct |
|
|
244
|
+
|---|---|
|
|
245
|
+
| `SUBMIT report VIA JOB` | `cl_apj_rt_api=>schedule_job()` |
|
|
246
|
+
| `CALL FUNCTION...IN BACKGROUND TASK` | Application Job |
|
|
247
|
+
| SM36 / SM37 | Fiori app "Application Jobs" |
|
|
248
|
+
| `sy-datum` in job class | `cl_abap_context_info=>get_system_date()` |
|
|
249
|
+
| No logging in job | Use `cl_bali_log` for execution monitoring |
|
|
250
|
+
| Hardcoded schedule in code | Use Job Template + admin scheduling |
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# ABAP Cloud Communication — HTTP client, communication scenarios, outbound calls
|
|
2
|
+
|
|
3
|
+
## Communication Scenario Architecture
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
ABAP Cloud App
|
|
7
|
+
→ Communication Arrangement (config in Fiori launchpad)
|
|
8
|
+
→ Communication System (target host + auth)
|
|
9
|
+
→ Communication Scenario (defines what services are consumed)
|
|
10
|
+
→ Outbound Service (HTTP, RFC, SOAP)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Define Communication Scenario (Developer)
|
|
14
|
+
|
|
15
|
+
```abap
|
|
16
|
+
" 1. Create Communication Scenario in ADT:
|
|
17
|
+
" - Name: Z_CS_EXTERNAL_API
|
|
18
|
+
" - Allowed instances: 1 (or more)
|
|
19
|
+
" - Add Outbound Service:
|
|
20
|
+
" Service ID: Z_OS_EXT_API
|
|
21
|
+
" Service Type: HTTP
|
|
22
|
+
" URL path: /api/v1
|
|
23
|
+
" Default port: 443
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## HTTP Client — Outbound Call (Cloud Pattern)
|
|
27
|
+
|
|
28
|
+
```abap
|
|
29
|
+
CLASS zcl_external_api DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
|
30
|
+
PUBLIC SECTION.
|
|
31
|
+
METHODS call_api
|
|
32
|
+
IMPORTING iv_order_id TYPE numc10
|
|
33
|
+
RETURNING VALUE(rs_result) TYPE zs_api_result
|
|
34
|
+
RAISING cx_static_check.
|
|
35
|
+
ENDCLASS.
|
|
36
|
+
|
|
37
|
+
CLASS zcl_external_api IMPLEMENTATION.
|
|
38
|
+
METHOD call_api.
|
|
39
|
+
" 1. Get HTTP destination from communication arrangement
|
|
40
|
+
DATA(lo_dest) = cl_http_destination_provider=>create_by_comm_arrangement(
|
|
41
|
+
comm_scenario = 'Z_CS_EXTERNAL_API'
|
|
42
|
+
service_id = 'Z_OS_EXT_API' ).
|
|
43
|
+
|
|
44
|
+
" 2. Create HTTP client
|
|
45
|
+
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_dest ).
|
|
46
|
+
|
|
47
|
+
" 3. Build request
|
|
48
|
+
DATA(lo_request) = lo_client->get_http_request( ).
|
|
49
|
+
lo_request->set_uri_path( |/api/v1/orders/{ iv_order_id }| ).
|
|
50
|
+
lo_request->set_header_field(
|
|
51
|
+
i_name = 'Accept'
|
|
52
|
+
i_value = 'application/json' ).
|
|
53
|
+
|
|
54
|
+
" 4. Execute
|
|
55
|
+
DATA(lo_response) = lo_client->execute( if_web_http_client=>get ).
|
|
56
|
+
|
|
57
|
+
" 5. Process response
|
|
58
|
+
DATA(lv_status) = lo_response->get_status( )-code.
|
|
59
|
+
DATA(lv_body) = lo_response->get_text( ).
|
|
60
|
+
|
|
61
|
+
IF lv_status <> 200.
|
|
62
|
+
RAISE EXCEPTION TYPE zcx_api_error
|
|
63
|
+
EXPORTING textid = zcx_api_error=>http_error
|
|
64
|
+
mv_status = lv_status
|
|
65
|
+
mv_body = lv_body.
|
|
66
|
+
ENDIF.
|
|
67
|
+
|
|
68
|
+
" 6. Parse JSON response
|
|
69
|
+
xco_cp_json=>data->from_string( lv_body )->write_to( REF #( rs_result ) ).
|
|
70
|
+
|
|
71
|
+
" 7. Close client
|
|
72
|
+
lo_client->close( ).
|
|
73
|
+
ENDMETHOD.
|
|
74
|
+
ENDCLASS.
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## HTTP Methods
|
|
78
|
+
|
|
79
|
+
```abap
|
|
80
|
+
" GET
|
|
81
|
+
DATA(lo_resp) = lo_client->execute( if_web_http_client=>get ).
|
|
82
|
+
|
|
83
|
+
" POST
|
|
84
|
+
lo_request->set_text( lv_json_body ).
|
|
85
|
+
lo_request->set_header_field( i_name = 'Content-Type' i_value = 'application/json' ).
|
|
86
|
+
DATA(lo_resp) = lo_client->execute( if_web_http_client=>post ).
|
|
87
|
+
|
|
88
|
+
" PUT
|
|
89
|
+
DATA(lo_resp) = lo_client->execute( if_web_http_client=>put ).
|
|
90
|
+
|
|
91
|
+
" PATCH
|
|
92
|
+
DATA(lo_resp) = lo_client->execute( if_web_http_client=>patch ).
|
|
93
|
+
|
|
94
|
+
" DELETE
|
|
95
|
+
DATA(lo_resp) = lo_client->execute( if_web_http_client=>delete ).
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Response Handling
|
|
99
|
+
|
|
100
|
+
```abap
|
|
101
|
+
" Status code
|
|
102
|
+
DATA(lv_status) = lo_response->get_status( )-code. " 200, 404, 500
|
|
103
|
+
DATA(lv_reason) = lo_response->get_status( )-reason. " 'OK', 'Not Found'
|
|
104
|
+
|
|
105
|
+
" Body
|
|
106
|
+
DATA(lv_text) = lo_response->get_text( ). " string
|
|
107
|
+
DATA(lv_xstr) = lo_response->get_binary( ). " xstring
|
|
108
|
+
|
|
109
|
+
" Headers
|
|
110
|
+
DATA(lv_content_type) = lo_response->get_header_field( 'Content-Type' ).
|
|
111
|
+
|
|
112
|
+
" JSON → ABAP
|
|
113
|
+
DATA ls_result TYPE zs_api_result.
|
|
114
|
+
xco_cp_json=>data->from_string( lv_text )->write_to( REF #( ls_result ) ).
|
|
115
|
+
|
|
116
|
+
" JSON → internal table
|
|
117
|
+
DATA lt_items TYPE STANDARD TABLE OF zs_item.
|
|
118
|
+
xco_cp_json=>data->from_string( lv_text )->write_to( REF #( lt_items ) ).
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## POST with JSON Body
|
|
122
|
+
|
|
123
|
+
```abap
|
|
124
|
+
" ABAP → JSON
|
|
125
|
+
DATA(lv_json) = xco_cp_json=>data->from_abap(
|
|
126
|
+
VALUE zs_order_request(
|
|
127
|
+
customer_id = 'CUST100'
|
|
128
|
+
amount = 500
|
|
129
|
+
items = VALUE #(
|
|
130
|
+
( product_id = 'PROD001' quantity = 2 )
|
|
131
|
+
( product_id = 'PROD002' quantity = 1 ) ) )
|
|
132
|
+
)->to_string( ).
|
|
133
|
+
|
|
134
|
+
" Set body and content type
|
|
135
|
+
lo_request->set_text( lv_json ).
|
|
136
|
+
lo_request->set_header_field( i_name = 'Content-Type' i_value = 'application/json' ).
|
|
137
|
+
|
|
138
|
+
" Execute POST
|
|
139
|
+
DATA(lo_response) = lo_client->execute( if_web_http_client=>post ).
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## URL Parameters
|
|
143
|
+
|
|
144
|
+
```abap
|
|
145
|
+
" Query parameters
|
|
146
|
+
lo_request->set_uri_path( '/api/v1/orders' ).
|
|
147
|
+
lo_request->set_query(
|
|
148
|
+
i_query = |status=open&limit=50&offset=0| ).
|
|
149
|
+
|
|
150
|
+
" Or build path with parameters
|
|
151
|
+
lo_request->set_uri_path(
|
|
152
|
+
|/api/v1/orders?status=open&customer={ cl_web_http_utility=>encode_url( lv_customer ) }| ).
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Authentication Types (Communication Arrangement)
|
|
156
|
+
|
|
157
|
+
| Type | Use |
|
|
158
|
+
|------|-----|
|
|
159
|
+
| **Basic Authentication** | User/password (simple, legacy) |
|
|
160
|
+
| **OAuth 2.0 Client Credentials** | Machine-to-machine (most common for APIs) |
|
|
161
|
+
| **OAuth 2.0 SAML Bearer** | User propagation (principal propagation) |
|
|
162
|
+
| **Client Certificate** | mTLS |
|
|
163
|
+
| **No Authentication** | Public APIs |
|
|
164
|
+
|
|
165
|
+
Authentication is configured in the **Communication Arrangement** (Fiori launchpad), not in code.
|
|
166
|
+
|
|
167
|
+
## Consume OData Service (Cloud)
|
|
168
|
+
|
|
169
|
+
```abap
|
|
170
|
+
" Create destination for OData service
|
|
171
|
+
DATA(lo_dest) = cl_http_destination_provider=>create_by_comm_arrangement(
|
|
172
|
+
comm_scenario = 'Z_CS_ODATA_SRV'
|
|
173
|
+
service_id = 'Z_OS_ODATA' ).
|
|
174
|
+
|
|
175
|
+
" Create HTTP client
|
|
176
|
+
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_dest ).
|
|
177
|
+
|
|
178
|
+
" OData GET
|
|
179
|
+
DATA(lo_request) = lo_client->get_http_request( ).
|
|
180
|
+
lo_request->set_uri_path( '/sap/opu/odata/sap/API_BUSINESS_PARTNER/A_BusinessPartner' ).
|
|
181
|
+
lo_request->set_header_field( i_name = 'Accept' i_value = 'application/json' ).
|
|
182
|
+
lo_request->set_query( '$top=10&$filter=BusinessPartner eq ''1000000''' ).
|
|
183
|
+
|
|
184
|
+
DATA(lo_response) = lo_client->execute( if_web_http_client=>get ).
|
|
185
|
+
DATA(lv_json) = lo_response->get_text( ).
|
|
186
|
+
lo_client->close( ).
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Error Handling Pattern
|
|
190
|
+
|
|
191
|
+
```abap
|
|
192
|
+
METHOD call_api.
|
|
193
|
+
TRY.
|
|
194
|
+
DATA(lo_dest) = cl_http_destination_provider=>create_by_comm_arrangement(
|
|
195
|
+
comm_scenario = 'Z_CS_API'
|
|
196
|
+
service_id = 'Z_OS_API' ).
|
|
197
|
+
|
|
198
|
+
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_dest ).
|
|
199
|
+
|
|
200
|
+
DATA(lo_response) = lo_client->execute( if_web_http_client=>get ).
|
|
201
|
+
DATA(lv_status) = lo_response->get_status( )-code.
|
|
202
|
+
|
|
203
|
+
IF lv_status >= 400.
|
|
204
|
+
RAISE EXCEPTION TYPE zcx_api_error
|
|
205
|
+
EXPORTING mv_status = lv_status
|
|
206
|
+
mv_body = lo_response->get_text( ).
|
|
207
|
+
ENDIF.
|
|
208
|
+
|
|
209
|
+
rs_result = parse_response( lo_response->get_text( ) ).
|
|
210
|
+
|
|
211
|
+
CATCH cx_http_dest_provider_error INTO DATA(lx_dest).
|
|
212
|
+
" Communication arrangement not configured
|
|
213
|
+
RAISE EXCEPTION TYPE zcx_api_error
|
|
214
|
+
EXPORTING previous = lx_dest
|
|
215
|
+
textid = zcx_api_error=>comm_arrangement_missing.
|
|
216
|
+
|
|
217
|
+
CATCH cx_web_http_client_error INTO DATA(lx_http).
|
|
218
|
+
" Network/connection error
|
|
219
|
+
RAISE EXCEPTION TYPE zcx_api_error
|
|
220
|
+
EXPORTING previous = lx_http
|
|
221
|
+
textid = zcx_api_error=>connection_failed.
|
|
222
|
+
|
|
223
|
+
CLEANUP.
|
|
224
|
+
IF lo_client IS BOUND.
|
|
225
|
+
lo_client->close( ).
|
|
226
|
+
ENDIF.
|
|
227
|
+
ENDTRY.
|
|
228
|
+
ENDMETHOD.
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Setup Steps (Admin — Fiori Launchpad)
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
1. Communication System (target)
|
|
235
|
+
- Host: api.example.com
|
|
236
|
+
- Port: 443
|
|
237
|
+
- Auth: OAuth 2.0 Client Credentials
|
|
238
|
+
- Token endpoint: https://auth.example.com/oauth/token
|
|
239
|
+
- Client ID / Secret
|
|
240
|
+
|
|
241
|
+
2. Communication Arrangement
|
|
242
|
+
- Scenario: Z_CS_EXTERNAL_API
|
|
243
|
+
- Communication System: (from step 1)
|
|
244
|
+
- Outbound Service: Z_OS_EXT_API → active
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Rules
|
|
248
|
+
- Cloud: ALWAYS use `cl_http_destination_provider=>create_by_comm_arrangement` — never hardcode URLs
|
|
249
|
+
- Cloud: NEVER store credentials in code — always in Communication Arrangement
|
|
250
|
+
- Always close HTTP client in CLEANUP or after use
|
|
251
|
+
- Use XCO JSON for serialization/deserialization (no /ui2/cl_json in Cloud)
|
|
252
|
+
- Handle both HTTP errors (status >= 400) and connection errors (exceptions)
|
|
253
|
+
- URL-encode user input in query parameters: `cl_web_http_utility=>encode_url()`
|
|
254
|
+
- Communication Scenario = developer artifact; Communication Arrangement = admin config
|
|
255
|
+
|
|
256
|
+
## Anti-Patterns
|
|
257
|
+
| Anti-Pattern | Correct |
|
|
258
|
+
|---|---|
|
|
259
|
+
| `cl_http_client=>create_by_url( 'https://...' )` | `cl_http_destination_provider=>create_by_comm_arrangement()` |
|
|
260
|
+
| Hardcoded URLs in code | Communication Arrangement |
|
|
261
|
+
| Credentials in source code | Communication System config |
|
|
262
|
+
| `/ui2/cl_json=>serialize()` in Cloud | `xco_cp_json=>data->from_abap()` |
|
|
263
|
+
| Missing `lo_client->close()` | Always close in CLEANUP block |
|
|
264
|
+
| Missing error handling for HTTP status | Check `get_status()-code >= 400` |
|
|
265
|
+
| `CALL FUNCTION 'HTTP_...'` | Cloud HTTP client classes |
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# ABAP Cloud — language version, restricted statements, migration patterns
|
|
2
|
+
|
|
3
|
+
## Language Versions
|
|
4
|
+
|
|
5
|
+
| Version | Where | Access |
|
|
6
|
+
|---------|-------|--------|
|
|
7
|
+
| **ABAP for Cloud Development** | S/4HANA Cloud, BTP ABAP Environment | Released APIs only |
|
|
8
|
+
| **Standard ABAP** | S/4HANA on-premise, ECC | All APIs (including unreleased) |
|
|
9
|
+
| **ABAP for Key Users** | S/4HANA Cloud | Custom fields, custom logic (limited) |
|
|
10
|
+
|
|
11
|
+
```abap
|
|
12
|
+
" Set language version on class/program
|
|
13
|
+
@AbapCatalog.compiler.abapLanguageVersion: #ABAP_FOR_CLOUD_DEVELOPMENT
|
|
14
|
+
CLASS zcl_my_cloud_class DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Prohibited Statements in Cloud
|
|
18
|
+
|
|
19
|
+
```abap
|
|
20
|
+
" === SCREEN / DYNPRO ===
|
|
21
|
+
WRITE ... " prohibited — use CL_DEMO_OUTPUT or if_oo_adt_classrun
|
|
22
|
+
CALL SCREEN ... " prohibited — use RAP + Fiori
|
|
23
|
+
SET SCREEN ... " prohibited
|
|
24
|
+
LEAVE TO SCREEN ... " prohibited
|
|
25
|
+
SELECTION-SCREEN ... " prohibited
|
|
26
|
+
PARAMETERS ... " prohibited
|
|
27
|
+
SELECT-OPTIONS ... " prohibited
|
|
28
|
+
|
|
29
|
+
" === REPORTS / PROGRAMS ===
|
|
30
|
+
REPORT ... " prohibited — use classes
|
|
31
|
+
SUBMIT ... " prohibited — use application jobs
|
|
32
|
+
CALL TRANSACTION ... " prohibited
|
|
33
|
+
LEAVE TO TRANSACTION ... " prohibited
|
|
34
|
+
MESSAGE ... DISPLAY LIKE ... " prohibited
|
|
35
|
+
|
|
36
|
+
" === DATABASE (legacy) ===
|
|
37
|
+
SELECT ... ENDSELECT " prohibited — use INTO TABLE
|
|
38
|
+
EXEC SQL ... ENDEXEC " prohibited — use ABAP SQL or AMDP
|
|
39
|
+
OPEN CURSOR / FETCH / CLOSE " prohibited — use PACKAGE SIZE
|
|
40
|
+
|
|
41
|
+
" === FUNCTION MODULES (unreleased) ===
|
|
42
|
+
CALL FUNCTION 'unreleased_FM' " prohibited — only released FMs allowed
|
|
43
|
+
CALL FUNCTION ... IN UPDATE TASK " prohibited — use RAP save sequence
|
|
44
|
+
CALL FUNCTION ... STARTING NEW TASK " prohibited — use application jobs
|
|
45
|
+
|
|
46
|
+
" === FILE SYSTEM ===
|
|
47
|
+
OPEN DATASET ... " prohibited — use XCO or cloud file APIs
|
|
48
|
+
READ DATASET ... " prohibited
|
|
49
|
+
TRANSFER ... " prohibited
|
|
50
|
+
DELETE DATASET ... " prohibited
|
|
51
|
+
|
|
52
|
+
" === OTHER ===
|
|
53
|
+
GENERATE SUBROUTINE POOL ... " prohibited
|
|
54
|
+
CALL 'system_function' " prohibited
|
|
55
|
+
SYSTEM-CALL ... " prohibited
|
|
56
|
+
AUTHORITY-CHECK ... " prohibited in RAP — use BDEF authorization
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Cloud Equivalents — Migration Patterns
|
|
60
|
+
|
|
61
|
+
| Classic (Prohibited) | Cloud Equivalent |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `WRITE` / `REPORT` | `if_oo_adt_classrun~main( )` for console output |
|
|
64
|
+
| `CALL FUNCTION 'FM'` | Released class methods or wrapper |
|
|
65
|
+
| `SELECT...ENDSELECT` | `SELECT...INTO TABLE @DATA(lt)` + `LOOP AT lt` |
|
|
66
|
+
| `CALL TRANSACTION` | RAP + Fiori Elements |
|
|
67
|
+
| `SUBMIT report` | Application Jobs (`cl_apj_rt_api`) |
|
|
68
|
+
| `AUTHORITY-CHECK` | RAP BDEF `authorization master` |
|
|
69
|
+
| `OPEN DATASET` | `xco_cp_file=>for( )` or cloud file APIs |
|
|
70
|
+
| `READ TABLE...BINARY SEARCH` | `SORTED TABLE` + table expression |
|
|
71
|
+
| `DESCRIBE TABLE...LINES` | `lines( itab )` |
|
|
72
|
+
| `MOVE-CORRESPONDING` | `CORRESPONDING #( source )` |
|
|
73
|
+
| `CREATE OBJECT` | `NEW zcl_class( )` |
|
|
74
|
+
| `TRANSLATE...TO UPPER` | `to_upper( text )` |
|
|
75
|
+
| `CONCATENATE...INTO` | String template `\| \|` or `&&` |
|
|
76
|
+
| `CALL FUNCTION 'GUID_CREATE'` | `cl_system_uuid=>create_uuid_x16_static( )` |
|
|
77
|
+
| `CALL FUNCTION 'POPUP_TO_CONFIRM'` | Fiori MessageBox (frontend) |
|
|
78
|
+
| `SY-SUBRC after SELECT` | `IF lt IS INITIAL` or `SELECT SINGLE @abap_true` |
|
|
79
|
+
| `MESSAGE e001(zmsg)` | Exception class with `if_t100_message` |
|
|
80
|
+
|
|
81
|
+
## Console Output (classrun)
|
|
82
|
+
|
|
83
|
+
```abap
|
|
84
|
+
CLASS zcl_test DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
|
85
|
+
PUBLIC SECTION.
|
|
86
|
+
INTERFACES if_oo_adt_classrun.
|
|
87
|
+
ENDCLASS.
|
|
88
|
+
|
|
89
|
+
CLASS zcl_test IMPLEMENTATION.
|
|
90
|
+
METHOD if_oo_adt_classrun~main.
|
|
91
|
+
SELECT * FROM ztab_order INTO TABLE @DATA(lt_orders).
|
|
92
|
+
out->write( lt_orders ).
|
|
93
|
+
out->write( |Found { lines( lt_orders ) } orders| ).
|
|
94
|
+
ENDMETHOD.
|
|
95
|
+
ENDCLASS.
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Release Contracts (API Stability)
|
|
99
|
+
|
|
100
|
+
| Contract | Meaning | Use |
|
|
101
|
+
|:--------:|---------|-----|
|
|
102
|
+
| **C0** | Not released | Cannot use in Cloud |
|
|
103
|
+
| **C1** | Released for use | Safe to use in Cloud ABAP |
|
|
104
|
+
| **C2** | Released for use as remote API | Callable via RFC/HTTP |
|
|
105
|
+
| **C3** | Released for use in key user apps | Available in custom logic |
|
|
106
|
+
|
|
107
|
+
```abap
|
|
108
|
+
" Check if API is released:
|
|
109
|
+
" ADT → Open class → check @API annotation or release state
|
|
110
|
+
" Or: ATC check with cloud readiness profile
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## ATC Cloud Readiness Check
|
|
114
|
+
|
|
115
|
+
```abap
|
|
116
|
+
" Run ATC in ADT:
|
|
117
|
+
" 1. Right-click object → Run As → ABAP Test Cockpit
|
|
118
|
+
" 2. Select check variant: ABAP_CLOUD_READINESS
|
|
119
|
+
" 3. Review findings — each shows prohibited statement + suggested replacement
|
|
120
|
+
|
|
121
|
+
" Or programmatically:
|
|
122
|
+
" Use CDS view I_APIsForCloudDevelopment to query released APIs
|
|
123
|
+
SELECT * FROM I_APIsForCloudDevelopment
|
|
124
|
+
WHERE ObjectType = 'CLAS'
|
|
125
|
+
INTO TABLE @DATA(lt_released).
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Environments
|
|
129
|
+
|
|
130
|
+
| Environment | Language Version | Notes |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| **BTP ABAP Environment (Steampunk)** | Cloud only | No access to on-premise tables/FMs |
|
|
133
|
+
| **S/4HANA Cloud, public edition** | Cloud only | No custom code except key user + developer extensibility |
|
|
134
|
+
| **S/4HANA Cloud, private edition** | Cloud or Standard (opt-in) | Can enable Cloud for new development |
|
|
135
|
+
| **S/4HANA on-premise** | Cloud or Standard (opt-in) | Tier 1 (Cloud) or Tier 2 (Standard) |
|
|
136
|
+
|
|
137
|
+
## Tier Model (on-premise)
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
Tier 1 — ABAP for Cloud Development
|
|
141
|
+
├── Released APIs only
|
|
142
|
+
├── CDS view entities
|
|
143
|
+
├── RAP business objects
|
|
144
|
+
└── Clean ABAP patterns
|
|
145
|
+
|
|
146
|
+
Tier 2 — Standard ABAP (classic)
|
|
147
|
+
├── All APIs (released + unreleased)
|
|
148
|
+
├── Classic Dynpro / ALV / BAPI
|
|
149
|
+
└── Existing custom code
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
On S/4HANA on-premise, new development should target Tier 1 for future-proofing.
|
|
153
|
+
|
|
154
|
+
## Rules
|
|
155
|
+
- Cloud: ONLY use released APIs (check release state in ADT)
|
|
156
|
+
- Cloud: ALL DB access via ABAP SQL or CDS — no native SQL, no EXEC SQL
|
|
157
|
+
- Cloud: ALL UI via RAP + Fiori — no Dynpro, no ALV, no WRITE
|
|
158
|
+
- Cloud: Background processing via Application Jobs — no SUBMIT, no SM36
|
|
159
|
+
- Cloud: ALL business logic in classes — no reports, no function groups (except RAP handler)
|
|
160
|
+
- Cloud: Use `if_oo_adt_classrun` for console testing (replaces WRITE/REPORT)
|
|
161
|
+
- Cloud: Use exception classes for messages (replaces MESSAGE statement)
|
|
162
|
+
- Run ATC with ABAP_CLOUD_READINESS before moving code to Cloud
|
|
163
|
+
- New development on S/4HANA on-premise: target Tier 1 for upgrade path
|
|
164
|
+
|
|
165
|
+
## Anti-Patterns
|
|
166
|
+
| Anti-Pattern | Correct |
|
|
167
|
+
|---|---|
|
|
168
|
+
| `WRITE lv_value` | `out->write( lv_value )` via `if_oo_adt_classrun` |
|
|
169
|
+
| `CALL FUNCTION 'unreleased'` | Find released class equivalent or wrap |
|
|
170
|
+
| `SELECT...ENDSELECT` | `SELECT...INTO TABLE` + `LOOP AT` |
|
|
171
|
+
| `AUTHORITY-CHECK OBJECT` in RAP | `authorization master ( global )` in BDEF |
|
|
172
|
+
| Using unreleased CDS views (C0) | Use released I_* views (C1) |
|
|
173
|
+
| `SUBMIT zreport` for background | Application Job with `cl_apj_rt_api` |
|
|
174
|
+
| `MESSAGE e001(zmsg)` | Exception class implementing `if_t100_message` |
|
|
175
|
+
| Code in FORM/PERFORM | Code in class methods |
|
|
176
|
+
| Function group for business logic | Class + interface |
|