Sap Code Inspector how to use cl_ci_objectset class - abap

I tried to use the cl_ci_objectset class to reference a set of objects to run a inspection afterwards:
data: lr_ci_objectset type ref to cl_ci_objectset.
CALL METHOD cl_ci_objectset=>get_ref
EXPORTING
P_OBJSNAM = 'ZTEST'
RECEIVING
p_ref = lr_ci_objectset
EXCEPTIONS
... exception list ...
IF sy-subrc <> 0.
MESSAGE i005(zsci).
* Fehler beim Ermitteln der Objektmenge
RAISE cancel.
ENDIF.
* Prüfen, ob es überhaupt Objekte in der SCI Objektmenge gibt
IF lr_ci_objectset->iobjlst-objects[] IS INITIAL.
write 'Object Menge leer'.
* in diesem Fall kann auch nichts geprüft werden
RETURN.
ENDIF.
write 'Object Menge nicht leer'.
the set 'ZTEST' is exsisting in the system as a public object set.
after more testing i found the solution.
IF lr_ci_objectset->iobjlst-objects[] IS INITIAL.
is the wrong array for a objset and is therefore used.
IF lr_ci_objectset->OBJECTSINF IS INITIAL.
is functional.

You can't check whether "an object set is empty" that easily. Object sets can be either discrete sets of objects (just like the contents of a transport) or a set of selection criteria. The latter might or might not yield a list of objects when the selection is executed - so the resulting object list may be empty, even if the object set is not.

Related

Changes don't commit after RFC of ME_INFORECORD_MAINTAIN_MULTI

I'm calling ME_INFORECORD_MAINTAIN_MULTI with an RFC. The purchase info records get a new number, but the changes aren't commited to the db.
The commit is supposed to be implicit after a RFC, but it isn't. I've tried adding an explicit COMMIT WORK after the function call, but this didn't help.
The changes are commited properly if I use a regular function call (not remote), however performance is very slow.
Please help.
FORM CALL_BAPI_PIR.
lv_taskname = |PIR-{ lv_sentjobs WIDTH = 3 ALIGN = RIGHT PAD = '0' }|.
CALL FUNCTION 'ME_INFORECORD_MAINTAIN_MULTI'
STARTING NEW TASK lv_taskname
DESTINATION IN GROUP DEFAULT
PERFORMING RETURN_BAPI_PIR ON END OF TASK
EXPORTING
testrun = p_test
TABLES
t_eina = GT_ME_EINA
t_einax = GT_ME_EINAX
t_eine = GT_ME_EINE
t_einex = GT_ME_EINEX
return = GT_ME_INFORECORD_RETURN
EXCEPTIONS
system_failure = 1 MESSAGE lv_exceptionmsg
communication_failure = 2 MESSAGE lv_exceptionmsg
resource_failure = 3
.
CASE sy-subrc.
WHEN 0.
lv_sentjobs = lv_sentjobs + 1.
COMMIT WORK.
WHEN 1 OR 2.
MESSAGE lv_exceptionmsg TYPE 'I'.
WRITE: / lv_taskname, ':', lv_exceptionmsg.
ENDCASE.
ENDFORM.
FORM RETURN_BAPI_PIR USING TASKNAME.
DATA INFO LIKE RFCSI.
RECEIVE RESULTS FROM FUNCTION 'ME_INFORECORD_MAINTAIN_MULTI'
IMPORTING
RFCSI_EXPORT = INFO
RETURN = GT_ME_INFORECORD_RETURN.
lv_recvjobs = lv_recvjobs + 1.
ENDFORM.
I've solved this by making a wrapper function that ends with a commit, and calling the wrapper function instead of the standard function.
FUNCTION z_inforecord_maintain_mult2
IMPORTING
VALUE(testrun) TYPE bapiflag-bapiflag OPTIONAL
EXPORTING
VALUE(et_eina) TYPE mewieina_mig_t
VALUE(et_eine) TYPE mewieine_t
TABLES
t_eina TYPE mewieina_mig_t OPTIONAL
t_einax TYPE mewieinax_t OPTIONAL
t_eine TYPE mewieine_t OPTIONAL
t_einex TYPE mewieinex_t OPTIONAL
txt_lines TYPE mewipirtext_tt OPTIONAL
cond_validity TYPE mewivalidity_tt OPTIONAL
condition TYPE mewicondition_tt OPTIONAL
cond_scale_value TYPE mewiscaleval_tt OPTIONAL
cond_scale_quan TYPE mewiscalequan_tt OPTIONAL
return TYPE fs4mig_t_bapiret2 OPTIONAL.
CALL FUNCTION 'ME_INFORECORD_MAINTAIN_MULTI'
EXPORTING
testrun = testrun
IMPORTING
et_eina = et_eina
et_eine = et_eine
TABLES
t_eina = t_eina
t_einax = t_einax
t_eine = t_eine
t_einex = t_einex
txt_lines = txt_lines
cond_validity = cond_validity
condition = condition
cond_scale_value = cond_scale_value
cond_scale_quan = cond_scale_quan
return = return
.
IF SY-subrc = 0.
COMMIT WORK.
ENDIF.
ENDFUNCTION.
With RFC, there's an implicit database commit at some point of time in the calling program, but not in the RFC session, like there's no implicit database commit after SUBMIT.
You may chain several function module calls in the same RFC session, and to chain a SAP LUW commit in the RFC session you may call the function module BAPI_TRANSACTION_COMMIT to do a COMMIT WORK. The solution then depends on the type of RFC you use.
In your case, you use asynchronous RFC with a callback i.e. with wait, so the solution will be to
indicate KEEPING TASK at RECEIVE RESULTS so that to keep the RFC session open after calling ME_INFORECORD_MAINTAIN_MULTI
use WAIT FOR ASYNCHRONOUS TASKS so that BAPI_TRANSACTION_COMMIT is called sequentially after ME_INFORECORD_MAINTAIN_MULTI has ended.
CALL FUNCTION 'ME_INFORECORD_MAINTAIN_MULTI'
STARTING NEW TASK lv_taskname
DESTINATION IN GROUP DEFAULT
PERFORMING RETURN_BAPI_PIR ON END OF TASK
...
EXCEPTIONS
system_failure = 1 MESSAGE lv_exceptionmsg
communication_failure = 2 MESSAGE lv_exceptionmsg
resource_failure = 3.
IF sy-subrc = 0.
WAIT FOR ASYNCHRONOUS TASKS UNTIL lv_recvjobs = lv_sentjobs.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
STARTING NEW TASK lv_taskname " <====== reuse existing RFC session/closed implicitly right after
DESTINATION IN GROUP DEFAULT
EXCEPTIONS
system_failure = 1 MESSAGE lv_exceptionmsg
communication_failure = 2 MESSAGE lv_exceptionmsg
resource_failure = 3.
...
FORM RETURN_BAPI_PIR USING TASKNAME.
DATA INFO LIKE RFCSI.
RECEIVE RESULTS FROM FUNCTION 'ME_INFORECORD_MAINTAIN_MULTI'
KEEPING TASK " <============== add this to not close the RFC session
IMPORTING
RFCSI_EXPORT = INFO
RETURN = GT_ME_INFORECORD_RETURN.
lv_recvjobs = lv_recvjobs + 1.
ENDFORM.
NB:
I did not handle the exceptions to simplify the demonstration.
If you run the RFC under several task names, several RFC sessions are started, so you must call BAPI_TRANSACTION_COMMIT in each of these RFC sesssions.

Why is a DOORS Module sometimes null when trying to edit the Module via DXL?

I'm new to DXL programming language in IBM DOORS. However, I think I have managed to do many interesting things: create Modules, create Objects, create Links, delete Objects etc.
However, I have a very specific problem regarding "null" Modules. I've just written null between "" because the modules exist and they are referenced with a correct name.
When doing this:
Module m1 = edit("1. MY_MODULE", false)
save(m1)
close(m1)
An error like this appears:
enter image description here
You could not understand what does that mean as it is spanish. Basically states this: "Module null parameter in the first position of the argument." That means that the "m1" is null, as the parameter for save() method is null.
The point is that it is an error which appears only sometimes. It seems that the Module is null as it has been previously opened and DOORS does not close properly.
Is there any way, any method...whatever to avoid this error?
I assume that the script cannot find the module when another folder is active.
Try
Module m1 = edit ("/myproject/myfolder/mysubfolder/1. MY_MODULE", false)
There might be many reasons that the module can't be opened in edit mode. For example: User do not have write access OR Module is being used by other user, etc.
However, you can get around the error with the below code snippet:
Module m = edit('My_module', false)
if(!null m) {
//execute program
...
}
else {
//do something
}
I hope this helps.
How does your script work? do you open the same module again and again and sometimes get the error or do you open lots of modules and for some of them it works and for others it doesn't? In the latter case, perhaps you misspelled the path. You could add some sanity checks like
string fullPathToMod = "/myproject/myfolder.."
Item i = item fullPathToMod;
if null i then error "there is no item called " fullPathToMod
if "Module" != type i then error "there is an item, but it's not a module, it's a " type i
This is how the Code is structured:
void checkModule(string folderPath, string mName, Skip list, int listSize, int listLastIndex, string headers[], string heading[], string headerKey, bool uniqueKey, string combinedKey[]){
if (module mName){
Folder f = folder(folderPath)
current = f
Module m = edit(folderPath""mName, false)
current = m
Object o = first(m) // error sometimes: Se ha pasado un parametro Module null en una posición de argumento 1
if (o == null){
loadModule(m, list, listSize, listLastIndex, headers, heading)
} else {
updateModule(m, mName, list, listSize, listLastIndex, heading, headerKey, headers, uniqueKey, combinedKey)
save(m)
close(m)
}
if (lastError() != ""){
print "Error: " lastError() "\n"
}
} else {
print "No module " mName ".\n"
}
}
Exactly it breaks in line:
current = m
But as said, only sometimes, not always.
BTW, I'm executing this script via Batch, via Java code. One curious thing is that if I close DOORS, and execute the script it does execute correctly. It is as if it needs to be closed in order to edit modules correctly.
I pressume current can be used more than once with different types of Items. I guess it should not be wrong, but it breaks saying (more or less):
Null value passed to DXL commmand (current Module).
Obviously, it means that m is null, but I cannot see any reason for that.

ABAP Webdynpro error in supply function for a singleton

The following error text was processed in system EH5 : Invalid operand type for the MOVE-CORRESPONDING statement.
◾ The error occurred on the application server CRMEHP2_EH5_24 and in the work process 8 .
◾ The termination type was: RABAX_STATE
◾ The ABAP call stack was:
Method: IF_WD_CONTEXT_ELEMENT~GET_STATIC_ATTRIBUTES of program CL_WDR_CONTEXT_ELEMENT========CP
Method: BOOKINGS_READ of program /1BCWDY/0AA4D2ZOSMXD1LD8M8M2==CP
Method: BOOKINGS_READ of program /1BCWDY/0AA4D2ZOSMXD1LD8M8M2==CP
Method: SUPPLY_ELEMENTS of program CL_WDR_CONTEXT_NODE_VAL=======CP
Method: IF_WD_CONTEXT_NODE~GET_LEAD_SELECTION of program CL_WDR_CONTEXT_NODE_VAL=======CP
Method: IF_WD_CONTEXT_NODE~GET_LEAD_SELECTION of program CL_WDR_CONTEXT_NODE_MAP=======CP
Method: GET_LEAD_SELECTION of program CL_WDR_TABLE_DATA_PROVIDER====CP
Method: UPDATE_RANGE_SELECT_START of program CL_WDR_TABLE_DATA_PROVIDER====CP
Method: GET_TABLE_DATA of program CL_WDR_TABLE_DATA_PROVIDER====CP
Method: GET_VISIBLE_TABLE_DATA of program CL_WDR_TABLE_DATA_PROVIDER====CP
I have created two controllers
Componentcontroller is bound to flightinfo table. This table is populated. However, if_componentcontroller=>element_flightinfo dosen't fetch any data. Why?
Customcontroller2 is bound to bookingtab table.
Method:
**METHOD bookings_read.**
DATA:
stru_flight TYPE if_componentcontroller=>element_flightinfo,
itab_booking TYPE if_customcontroller2=>elements_bookingtab.
* Get Parent Element.
* Error is here: All attributes of stru_flight are either blank or zero.
* The error disappears once CALL METHOD is commented.
CALL METHOD parent_element->get_static_attributes
IMPORTING
static_attributes = stru_flight.
* read bookings
*Rest of the satatements work fine.
SELECT * FROM sbook
INTO CORRESPONDING FIELDS OF TABLE itab_booking
WHERE carrid = stru_flight-carrid
AND connid = stru_flight-connid
AND fldate = stru_flight-fldate.
* bind all the elements
node->bind_table(
new_items = itab_booking
set_initial_elements = abap_true ).
**ENDMETHOD.**
Definition of parent_element, and stru_flights structure
NODE Importing IF_WD_CONTEXT_NODE
PARENT_ELEMENT Importing IF_WD_CONTEXT_ELEMENT
stru_flight TYPE if_componentcontroller=>element_flightinfo,
**CALL METHOD parent_element->get_static_attributes
IMPORTING
static_attributes = stru_flight.**
implicit constant definition for context node bookingtab types:
Element_bookingtab type SBOOK,
Elements_bookingtab type standard table of Element_bookingtab with default key.

SAP HR OM BAdI does not detecting IN_UPDATE changes

We have implemented BADI ZHR_INT_BAD_OM_INFTY and Method IN_UPDATE. Now when some users save their OM work the IN_UPDATE method is not triggered.
The problem with debugging this is that when you go into abap debugger "stuff" in the background gets committed.
Our goal is to have a list of recent OM changes for delta detection.
Example of the code we have implemented:
DATA:
lw_old_image LIKE LINE OF old_image,
lw_new_image LIKE LINE OF new_image,
ls_object TYPE hrobject.
"-- Check if there is anything interesing in the old image
LOOP AT old_image INTO lw_old_image
WHERE infty IN me->get_range_infotypes( )
AND begda LE sy-datum
AND endda GE sy-datum.
MOVE-CORRESPONDING lw_old_image TO ls_object.
"-- If an object has been detected, trigger the refresh
TRY.
zhr_cl_int_person_masterdata=>trigger_om_object_changed( zhr_cl_om_object=>get( im_plvar = ls_object-plvar
im_otype = ls_object-otype
im_objid = ls_object-objid ) ).
CATCH zcx_hr_om. " " Base class for OM objects
ENDTRY.
ENDLOOP.
"-- If nothing found, check if there is anything interesting in the new image
IF ls_object IS INITIAL.
LOOP AT new_image INTO lw_new_image
WHERE infty IN me->get_range_infotypes( )
AND begda LE sy-datum
AND endda GE sy-datum.
MOVE-CORRESPONDING lw_new_image TO ls_object.
"-- If an object has been detected, trigger the refresh
TRY.
zhr_cl_int_person_masterdata=>trigger_om_object_changed( zhr_cl_om_object=>get( im_plvar = ls_object-plvar
im_otype = ls_object-otype
im_objid = ls_object-objid ) ).
CATCH zcx_hr_om. " " Base class for OM objects
ENDTRY.
ENDLOOP.
ENDIF.

python3 - data type of input()

I need to assign a user-provided integer value to an object. My format is as follows:
object = input("Please enter an integer")
The following print tests...
print(type(object))
print(object)
...return <class 'str'> and '1'. Is there a way to set the data type of 'object' to the data type of the user's input value? IOW, such that if object=1, type(object)=int? I know I can set the data type of an input to int using the following:
object = int(input("Please enter an integer"))
In this case, if the user does not provide an int, the console throws a traceback error and the program crashes. I would prefer to test whether the object is in fact an int; if not, use my program to print an error statement and recursively throw the previous prompt.
while True:
try:
object = int(input("Please enter an integer"))
break
except ValueError:
print("Invalid input. Please try again")
print(type(object))
print(object)
You can always catch a "traceback error" and substitute your own error handling.
user_input = input("Please enter an integer")
try:
user_number = int(user_input)
except ValueError:
print("You didn't enter an integer!")