Is there any way to check if RFC exists in a SAP system - abap

I'm developing an ABAP PROGRAM which calls RFC from differrent SAP systems. Is there any way to check if the RFC exists in the destination system before calling the RFC?

You can use FM FUNCTION_EXISTS to check, if an FM exists or not. Obviously you have to call it remotly. Roughly:
CALL FUNCTION 'FUNCTION_EXISTS'
DESTINATION ...
EXPORTING
funcname = 'xxx' => enter the FM here, which has to be checked
* IMPORTING
* GROUP =
* INCLUDE =
* NAMESPACE =
* STR_AREA =
EXCEPTIONS
FUNCTION_NOT_EXIST = 1
OTHERS = 2.
If the FM exists, the importing parameters will have valid values, otherwise FUNCTION_NOT_EXIT exception will be raised.

Most common way in my opinion is to use RFC_PING:
CALL FUNCTION 'RFC_PING' DESTINATION <your destination here>.

Related

How to read ABAP code using a java client

I have a requirement were I need to read ABAP code written by SAP developers. I want to write my own client using Java/Python which can integrate with SAP system and get me the ABAP code.
What I understand that ABAP code is stored in SAP database like HANA, mysql etc. So is there a way which SAP provides where we can read the code like we can do in Git/SVN etc.
I've used RFC calls RPY_FUNCTIONMODULE_READ and RPY_FUNCTIONMODULE_READ_NEW through the perl NWRFC wrapper/library to retreive ABAP code.
You can access tables with below techniques:
Using SAP Connectors via RFC (RFC_READ_TABLE)
Using SOAP Web Service with same function (RFC_READ_TABLE)
Using custom web services with existing functions which are reading report, functions, etc.
You can use both Java or Pyhton for RFC, there is already exits github repo for python.
If you will select reading directly in db table, you need to know structure of saved data. It has own mechanism for OOP objects. Daniel Berlin try to implement binary parser in C++ in sap-reposrc-decompressor project. Never forget this source depended with SAP version.
I think using ADT (ABAP Development Tools) plugin is good for updated systems. There is already Eclipse plugin exists for ADT. ADT not exists in old systems.
If you are planning to use your solution in old system (after 7.01), you can build your own solution with abapGit and custom web services.
NOTE: Keep in mind, report and data elements (variables, tables, types) saved in separate tables. Dynpro objects (screens etc), reports (Smartforms) hard things to decompile.
Before you re-invent a wheel, Take a look at:
ABAPgit. https://docs.abapgit.org/
or the old SAPLink https://wiki.scn.sap.com/wiki/display/ABAP/SAPlink.
If you want JUST the source code, You could expose a very simple rest service/ Endpoint in SAP.
This service would just read the raw code and return it as plain text.
Every abaper could create this for you.
BUT is the raw source only. There is much more to a complete development
and why tools like ABAPGIT exist.
In SICF, create a new endpoint / service.
EG ZCODE_MONKEY with the class below as an example.
Now activate the service.
Call the endpoint
http://server:PORT/zcode_monkey?name=ZCODE_MONKEY
Sample implementation
CLASS zcode_monkey DEFINITION
PUBLIC
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES: if_http_extension.
ENDCLASS.
CLASS zcode_monkey IMPLEMENTATION.
METHOD if_http_extension~handle_request.
DATA: lo_src type ref to CL_OO_SOURCE,
l_name TYPE string,
l_repname type c length 30,
l_clskey type seoclskey ,
l_source type rswsourcet,
resultcode TYPE string.
FIELD-SYMBOLS: <line> TYPE LINE OF rswsourcet.
l_name = server->request->get_form_field( name = 'NAME' ).
l_clskey = l_name.
l_repname = l_name.
create OBJECT lo_src
EXPORTING
clskey = l_clskey
EXCEPTIONS
class_not_existing = 1
others = 2 .
IF sy-subrc <> 0.
read REPORT l_repname into l_source.
else.
lo_src->read( ).
lo_src->if_oo_clif_source~get_source( IMPORTING source = l_source ).
ENDIF.
LOOP AT l_source ASSIGNING <line>.
CONCATENATE resultCode
cl_abap_char_utilities=>cr_lf
<line>
INTO resultCode RESPECTING BLANKS. " always show respect ;)
ENDLOOP.
SErver->response->set_content_type( content_type = 'text/plain' ).
server->response->set_cdata( EXPORTING data = resultcode ).
server->response->set_status(
EXPORTING
code = 200
reason = 'this is a 3.50 piece of code. Dont ask...its a demo ' ).
ENDMETHOD.
ENDCLASS.

How to add a whole package to transport request by code?

My task is to do all these steps programmatically:
Create a new transport request, I managed to do this with TR_INSERT_REQUEST_WITH_TASKS
Add package content to the newly created transport, this is the part I am stuck in.
Release the transport, I managed to do this with TR_RELEASE_REQUEST
My problem is that I can manually add the package to the transport request via transaction SE03 and then release it with FM TR_RELEASE_REQUEST, but that is not the goal, everything from step 1 to 3 has to happen in one program execution if anyone can guide me how to do step 2 it would be very helpful, thanks in advance.
In your program, you must :
First get the list of objects which belong to the package, via the table TADIR (object in columns PGMID, OBJECT, OBJ_NAME, and package in column DEVCLASS)
And add these objects to the task or transport request via the non-released function modules TRINT_APPEND_COMM or TR_APPEND_TO_COMM_OBJS_KEYS.
To add the whole project into request you must first select all the objects from package and add them one by one. You can do it like this:
DATA: l_trkorr TYPE trkorr,
l_package TYPE devclass VALUE 'ZPACKAGE'.
cl_pak_package_queries=>get_all_subpackages( EXPORTING im_package = l_package
IMPORTING et_subpackages = DATA(lt_descendant) ).
INSERT VALUE cl_pak_package_queries=>ty_subpackage_info( package = l_package ) INTO TABLE lt_descendant.
SELECT pgmid, object, obj_name FROM tadir
INTO TABLE #DATA(lt_segw_objects)
FOR ALL ENTRIES IN #lt_descendant
WHERE devclass = #lt_descendant-package.
DATA(instance) = cl_adt_cts_management=>create_instance( ).
LOOP AT lt_segw_objects ASSIGNING FIELD-SYMBOL(<fs_obj>).
TRY.
instance->insert_objects_in_wb_request( EXPORTING pgmid = <fs_obj>-pgmid
object = <fs_obj>-object
obj_name = CONV trobj_name( <fs_obj>-obj_name )
IMPORTING result = DATA(result)
request = DATA(request)
CHANGING trkorr = l_trkorr ).
CATCH cx_adt_cts_insert_error.
ENDTRY.
ENDLOOP.
Note, that you cannot add objects that are already locked in another request, it will give you cx_adt_cts_insert_error exception. There is no way to unlock objects programmatically, only via SE03 tool.
You can check code behind, Write Transport Entry in SE80 right click on package menu.

Copy_To_SQL command is throwing error when I am passing a valid schema name

We are trying to copy the data frame to Teradata specific database and the script is not accepting the schema_name parameter. Data Copy to User Database, which used in logon command is happening. But I tried to override the default and specifying Database Name in the copy_to_sql it is failing.
from teradataml import *
from teradataml.dataframe.copy_to import copy_to_sql
create_context(host = "ipaddrr", username='uname', password = "pwd")
df = DataFrame.from_query("select top 10* from dbc.tables;")
copy_to_sql(df = df ,table_name = 'Tab', schema_name='DB_Name',if_exists = 'replace')
Error: TeradataMlException: [Teradata][teradataml](TDML_2007) Invalid value(s) 'DB_Name' passed to argument 'schema_name', should be: A valid database/schema name..
Do you have a database / user named DB_Name? If not, try creating the database first and then running your copy script:
CREATE DATABASE DB_NAME FROM <parent_DB> AS PERMANENT = 1000000000;
I don't think the utilities / packages will typically create a database for you on the fly, since it can be a more involved operation (locks, space allocation, etc.) than creating a table.

Get Information about available parameters of report via XBP

I would like to get information about a report. I want to know which values are available if I call the report like this:
SUBMIT (IV_REPORT_NAME)
WITH SELECTION-TABLE selection_table
AND RETURN.
Here is my attempt:
FUNCTION /FOO/GET_REPORT_INFO.
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*" IMPORTING
*" VALUE(IV_REPORT_NAME) TYPE PROGRAMM
*" EXPORTING
*" VALUE(EV_RESULT_JSON) TYPE STRING
*"----------------------------------------------------------------------
DATA:
ld_return TYPE BAPIRET2,
it_selscreen_info TYPE STANDARD TABLE OF BAPI_SELSCREEN_INFO,"TABLES PARAM
wa_selscreen_info LIKE LINE OF it_selscreen_info,
it_selscreen_texts TYPE STANDARD TABLE OF TEXTPOOL,"TABLES PARAM
wa_selscreen_texts LIKE LINE OF it_selscreen_texts,
ld_external_user_name TYPE BAPIXMLOGR-EXTUSER.
ld_external_user_name = 'foo'.
CALL FUNCTION 'BAPI_XBP_READ_SELSCREEN'
EXPORTING
program = IV_REPORT_NAME
external_user_name = ld_external_user_name
IMPORTING
return = ld_return
TABLES
selscreen_info = it_selscreen_info
.
ev_result_json = /ui2/cl_json=>serialize( data = it_selscreen_info pretty_name = /ui2/cl_json=>pretty_mode-low_case ).
IF sy-subrc <> 0.
MESSAGE |Error sy-subrc: { sy-subrc }| TYPE 'E'.
ENDIF.
ENDFUNCTION.
But the result is always empty.
What am I doing wrong? Is BAPI_XBP_READ_SELSCREEN the right method for my goal?
This is an answer about "why BAPI_XBP_READ_SELSCREEN doesn't work", not an answer about the main question which is "how to retrieve selection screen parameters".
I'm not sure, but I guess BAPI_XBP_READ_SELSCREEN doesn't work because you don't apply the usual logic of XBP.
XBP ("eXternal Background Processing") is a library of APIs used to schedule jobs from an external scheduler. It's based on XMI ("eXternal Management Interface" Framework) which is used by other APIs, and which offers common features, especially the log.
XMI and the applications based on XMI are RFC-capable, so that they can be called remotely.
To use the APIs based on XMI, the minimum is to :
call the function module BAPI_XMI_LOGON to open a session to use a library of APIs you want to use.
For XBP, use the parameters INTERFACE = 'XBP' and VERSION = '3.0' (or the version you want).
The parameters EXTCOMPANY and EXTPRODUCT can be any max-16-characters names, as agreed with the administrators of the SAP software (they can be possibly blank too), and are subject to S_XMI_PROD authorizations if defined. If they are used with different XMI API libraries during the same RFC session, the same values must be passed.
call the APIs you want (BAPI_XBP_READ_SELSCREEN in your case).
Note that there's an "external user" parameter (usually EXTERNAL_USER_NAME), which is a free field, to be an identifier of the external application. This value is stored with the logs so that you may display or retrieve the XMI logs by external application (transaction RZ15).
call BAPI_XMI_LOGOFF
There is one INTERFACE parameter, whose value must be the same as the one used in BAPI_XMI_LOGON.
In case, you have called an API which updates data, call BAPI_TRANSACTION_COMMIT to commit these updates.
I've just tested BAPI_XBP_READ_SELSCREEN successfully with the program below (please handle the exceptions), so I think it's a good idea to use it :
DATA rfcdest TYPE rfcdest.
rfcdest = ''. " XBP is well suited for RFC, but this test doesn't need remote call.
CALL FUNCTION 'BAPI_XMI_LOGON'
DESTINATION rfcdest
EXPORTING
extcompany = 'ABAPERS&CO'
extproduct = 'NICEJOBSCHEDULER'
interface = 'XBP'
version = '3.0'.
DATA: selscreen_info TYPE STANDARD TABLE OF bapi_selscreen_info,
selscreen_texts TYPE STANDARD TABLE OF textpool.
CALL FUNCTION 'BAPI_XBP_READ_SELSCREEN'
DESTINATION rfcdest
EXPORTING
program = 'BTCAUX10'
external_user_name = 'SRO'
sel_text_lang = 'E' " English
TABLES
selscreen_info = selscreen_info
selscreen_texts = selscreen_texts.
CALL FUNCTION 'BAPI_XMI_LOGOFF'
DESTINATION rfcdest.
IF rfcdest IS NOT INITIAL. " if you use RFC, close the connection!
CALL FUNCTION 'RFC_CONNECTION_CLOSE'
EXPORTING
destination = rfcdest
EXCEPTIONS
destination_not_open = 1
OTHERS = 2.
ENDIF.
Please check user name "foo". If foo is not external user then result will be empty because of wrong external user.
regards,
Umar Abdullah

How to use insert_job

I want to run a Bigquery SQL query using insert method.
I ran the following code just like so:
JobConfigurationQuery = Google::Apis::BigqueryV2::JobConfigurationQuery
bq = Google::Apis::BigqueryV2::BigqueryService.new
scopes = [Google::Apis::BigqueryV2::AUTH_BIGQUERY]
bq.authorization = Google::Auth.get_application_default(scopes)
bq.authorization.fetch_access_token!
query_config = {query: "select colA from [dataset.table]"}
qr = JobConfigurationQuery.new(configuration:{query: query_config})
bq.insert_job(projectId, qr)
and I got an error as below:
Caught error invalid: Job configuration must contain exactly one job-specific configuration object (e.g., query, load, extract, spreadsheetExtract), but there were 0:
Please let me know how to use the insert_job method.
I'm not sure what client library you're using, but insert_job probably takes a JobConfiguration. You should create one of those and set the query parameter to equal your JobConfigurationQuery you've created.
This is necessary because you can insert various jobs (load, copy, extract) with different types of configurations to this one API method, and they all take a single configuration type with a subfield that specifies which type and details about the job to insert.
More info from BigQuery's documentation:
jobs.insert documentation
job resource: note the "configuration" field and its "query" subfield