When working with RFC-enabled Function Modules I often add custom return messages. These are defined as message classes with IDs and parameters. Now I receive those messages perfectly in my calling program, but since the caller can be on a different system the message classes I defined on the source system are unknown. Standard output of these messages to a message manager or application log fails as the text can't be generated.
What is the best practice for making these types of messages meaningful in the calling environment?
Is there an alternative to filling the text field in the source program, for instance by using MESSAGE_TEXT_BUILD? If I fill that text will standard SAP code not try to overwrite it from a non-existent message class?
Best option I can think of is to make your own RFC function module that takes in a message id, number, etc and returns a message string. You will have to distribute this to all the systems. You code it as:
FUNCTION zget_message.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(i_msgid) TYPE msgid
*" REFERENCE(i_msgno) TYPE msgno
*" REFERENCE(i_msgv1) TYPE msgv1
*" REFERENCE(i_msgv2) TYPE msgv1
*" REFERENCE(i_msgv3) TYPE msgv1
*" REFERENCE(i_msgv4) TYPE msgv1
*" EXPORTING
*" VALUE(e_message) TYPE string
*"----------------------------------------------------------------------
MESSAGE ID i_msgid TYPE 'I' NUMBER i_msgno
WITH i_msgv1 i_msgv2 i_msgv3 i_msgv4
INTO e_message.
ENDFUNCTION.
There is probably a SAP standard RFC that does this somewhere but I don't know what it is.
As far as i know, You should be informed,or it should be defined and documented, which messages a remote caller can use inside the remote system, so that the calling app just gets them back to show them. In terms of classes, which interfer on both systems, I do not know anything, that would prevent collisions/missing id's/classes. So You for Yourself will have to deal with that.
No, I researched, there is definetely no way to deal with that, You as developer should be aware, that any remote assigned messages are NOT used locally.
Related
I have a big string containing 400 MByte JSON data in rfc function module.
See debugger:
Unfortunately my pyRFC client only receives roughly 34 MByte.
Where and why does my data get cut?
Is this a well known limitation of sap-rfc?
Strange but true, I already transferred json strings with 77 MByte successfully.
Related issue at github: https://github.com/SAP/PyRFC/issues/97
It cannot be a limitation of SAP RFC. I have made a simple test. I created an RFC function module in one of the systems (let us name the RFC destination for it DEV000). It looks like this.
FUNCTION Z_TEST .
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*" EXPORTING
*" VALUE(E_STRING) TYPE STRING
*"----------------------------------------------------------------------
e_string = `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`.
DO 23 TIMES.
e_string = e_string && e_string.
ENDDO.
ENDFUNCTION.
Then I wrote a simple program in another system that calls this function module.
REPORT ZZZ.
DATA: g_string TYPE string.
CALL FUNCTION `Z_TEST`
DESTINATION `DEV000`
IMPORTING
e_string = g_string.
BREAK-POINT.
The string gets transferred in full, so it cannot be a limitation of SAP RFC. I guess you have to search for the cause rather in your pyRFC library or in your Python's client code.
I'm looking at the description of CALL - System Function Call in the SAP ABAP Keyword Definition. Such calls have the format CALL 'xxx' ID 'yyy' FIELD 'zzz'. The ABAP Keyword Definition does not mention that sy-subrc is set by calling a system function. But somehow, I suspect that it is.
Can I "trust" the Keyword Definition in such a case? (sy-subrc not mentioned => not set)
What would be a "good" example system function call to test it on an SAP system? (does not break/change anything, exists on all systems)
Note that I'm not an ABAP programmer and I usually handle third-party ABAP programs in Java as text / parse tree. I know that one usually should not call system functions, but the ABAP code I look at might have such calls. Furthermore, I'm not interested in the actual value a specific system call sets sy-subrc to, just in the fact whether system calls set/alter sy-subrc or not.
Well, as you are asking this question you are already aware this is NOT recommended approach to use direct SYSTEM calls. However, if you still want to use them...
By using CALL statement SAP kernel C-modules are called and without knowing the source we can not interpret the returning value confidently, either it's 0 or 1.
Despite there are examples (see line 230 of DYNP_VALUES_READ FM) where sy-subrc value is checked after system calls, nobody except SAP knows which value to check in certain case. Nor we.
Also there were reports (1, 2) about ambiguous meaning of these values during tests.
So the answer is NO, sy-subrc in this context brings no meaningful information.
P.S. Answering your questions:
No, you cannot interpret it that way. If something is not mentioned in ABAP Documentation then this not known for sure or not meaningful at all.
I cannot confirm this is good idea at all (to test system calls), but if you want you can try call SYSTEM function.
It calls arbitrary Unix command. For example, you can move files stored on your ABAP Server like this:
CALL 'SYSTEM'
ID 'COMMAND'
FIELD 'mv /usr/sap/temporary
/usr/sap/definite'.
Now this should be a safe call that works on any system:
DATA: dbserver TYPE char255.
CALL 'C_SAPGPARAM' ID 'NAME' FIELD 'SAPDBHOST'
ID 'VALUE' FIELD dbserver.
As you probably already know there are some exceptions that can occur. As for sy-subrc, when a command sets sy-subrc it is usually explicitly mentioned in the documentation including which values it can hold and their meaning. But don't quote me on that.
Simple (harmless) function modules are RH_GET_DATE_DAYNAME that requires the language and 10 character date (eg. 26.10.2016) as input fields and DATE_TO_DAY that only requires the 10 character date as input. The sy-subrc should be returned as 0 if a valid date is entered.
VB2010 with ArcObjects. Im having a problem recalling how to do this. I can test for an object type and then do something if it is the proper type. All else I want to display a message with the type that is not supported. So I have:
Dim pRasRenderer As IRasterRenderer
pRasRenderer = pRasterLayer.Renderer
If TypeOf pRasRenderer Is IRasterClassifyColorRampRenderer Then
'process the layer
Else
Debug.Print "Type not supported: " & pRasRenderer.ToString
End If
If not supported the print statement should read
"Type not supported: IRasterStretchColorRampRenderer"
or any of the other types that I do not process. But All I get back is
"Type not supported: System.__ComObject"
I tried GetType() and TypeName. Just cant remember if I can do this or not.
With COM, the type isn't IRasterStretchColorRampRenderer, it's some COM type that (most likely) implements quite a few distinctly different interfaces. Given that you're working from .NET, you'll get __ComObject any time you try to access the "type" of the object directly.
The actual "type" of the object which implements IRasterStretchColorRampRenderer, for example, is more than likely a native implementation of a COM CoClass. As such, you'll never get a "managed" type name from .NET code for this.
Unfortunately, this means that you're best solution is likely to report that the type passed in is not supported without trying to report the actual type passed into the method. This would likely be something like:
Debug.Print "Type not supported: Current layer is not using a Classify Color Ramp Renderer"
Out of interest, how are method names stored in memory in compiled Objective-C? The main reason of interest is understanding dynamic typing better.
Thanks in advance!
The source for the runtime is available, btw, if you really want to go deep.
In short; method names -- their selectors -- are stored as C strings in the mach-o of the binary. I.e. if you have a method -(void)foo:(int)a bar:(int)b;, there will be a selector foo:bar: string in the mach-o.
Type encoding information is also stored in a different segment of the mach-o file. That type information -- for which there is API in the runtime to retrieve it -- describes the type of the return value and arguments to the method.
Note that the type information is incomplete. Note also that using the type information to figure out how to generically encode/decode the arguments to and return value from a method is a downright pain.
How do I call the SAP report (for example RSPARAM) with help JCo?
What RFC may be used to remotely call SA38 transaction with RSPARAM (e.t.c.) as parameter and then return results for later work ?
RFC is for calling function modules, not programs. It's possible to use some generic function module to start a report, but since you'll usually want to process the results of the program and the program does not know that it was meant to deliver its results in a machine-readable way, you probably won't get too far this was. What exactly are you trying to do?
With the nearly infinite possible results of calling a transaction, i don't think there is a RFC to execute such an operation and return a result. What would be the result in case of an ALV display, or if the program then wait for some interactions ?
You can display a transaction in SAP portal using transactions Iviews. You're then using the portal page as a HTMLGui for your transaction.
also, some FM can sometime be used to perform operations instead of a full program (ie HR_INFOTYPE_OPERATION instead of pa30).
regards
Guillaume
Edition : since you want the result of RRSPARAM, you could encapsulate the "important" part (form SHOW_ACTUAL_PAR_VALUES_ALV) in a module function accessible by RFC, and returning a table of CST_RSPFPAR_ALV (ie the same structure that is displayed in the report)
regards
If You don't find a function to call, just create one by yourself. Tag it as callable from outside via RFC and in the coding, perform such things as "submit report xyz with param1 = value1 ... and return ... exporting list to memory". Then you can even return list output from this. Define the interface of the freshly created function module as you need (that means, report name as input, list output as a table of strings, e.g.). Attention, there is of course a big security risk, having an remote function accepting variable reportnames. But I am sure You know :-)