Anmeldedatum: 06.12.2002 Beiträge: 142
Autor:
Azreal Specialist
Folgender Guide soll die Welt des XI - genauer die Inbound Proxys der an XI angeschlossenen Systeme - etwas näher bringen. Das am Ende dieses Beitrages angehängte Coding simuliert einen Proxyaufruf vergleichbar mit dem Testreport SPRX_TEST_INBOUND. Der Vorteil dieses Reports ist jedoch, daß man die Möchkeit hat alle Eingaben im Vorraus zu definieren. Sodaß ein beherzter click auf den 'ausführen? Button reicht um die XML seiner Wahl in das System zu jagen.
Meine Intension dahinter war einfach die Tatsache, daß ich es Leid war bei der Implementierung eines Inboundproxys immer die gleichen Angaben in der SPRX_TEST_INBOUND machen zu müssen (auch eine Variante anzulegen war mir zu - naja). Zudem mußte ich damals andauernd in den Debugger springen und das Sendende System setzten (diese Funktion wird von dem Standardtestreport nicht unterstützt) Und wie es sich für einen Programmierer gehört ist dann folgender Report dabei herausgekommen.
Der Report gliedert sich im Grunde in vier Teile.
1. XML-String erstellen
Per concatenate wird hier das XML zusammengebastelt. Als Vorlage diente mir ein Original aus der SXMB_MONI. Gewisse Platzhalter lassen auch eine Generik zu. z.B. wie folgt:
| Code: |
| CONCATENATE l_xml_string '<ns1:Vorname>' lv_name '</Vorname>' INTO l_xml_string. |
Der konkatinierte String muß nun in einen RAW string umgewandelt werden. Am einfachsten geht das mittels folgender Klasse CL_ABAP_CONV_OUT_CE.
2. XML 2 ABAP Mapper
Im zweiten Schritt kommt der XML 2 ABAP mapper. Die Daten liegen derzeit ja im XML-Format vor. Innerhalb eines Proxies sind diese jedoch in einer generierten komplexen Struktur. Gemapped wird das ganze durch generiertes XSLT Mapping. Wie das Mapping aussehen soll zieht wird über das IFR ermittelt. Dazu ist es notwendig Namespace und Interface das aufgerufen werden soll zu nennen:
| Code: |
* Namespace des empfangenden Interfaces
lv_receiver-interface-namespace = 'XYZ_interface_namespace'.
* Empfangendes interface
lv_receiver-interface-name = 'XYZ_interface_name'. |
Entegen der sonst allgemeingltigen ABAP Zeichenkettenpolitik muß man hier die kompletten Namen nicht in Großbuchstaben schreiben, da diese Informationen vom IFR kommen und da dies Java ist wird nicht so auf Groß/Kleinschreibung geachtet.
Mit folgender Zeile werden die informationen über den Proxy gezogen:
| Code: |
| lo_registry = cl_proxy_inbound_registry=>create_from_ifr_name( p_interface = lv_receiver-interface ). |
Danach wird das passende XSLT gesucht:
| Code: |
| lo_xslt = cl_proxy_stylesheet_runtime=>create_from_method |
Existiert kein Mapping (z.B. beim Erstaufruf), dann wird schnell eins generiert:
| Code: |
| lo_xslt->generate( ). |
Nicht wundern, wenn das Mapping in der SE80 bei euren lokalen Objekten auftaucht - Das XSLT scheint immer bei dem User zu liegen der als erster die Codingzeilen durchläuft.
Danach wird aus den Interfacedaten noch die ABAPStruktur initialisiert. Und letztendlich wird Mapping mittels CALL TRANSFORMATION durchgeführt.
3. Senderparty festlegen
Das ist der Punkt, an dem SPRX_TEST_INBOUND nicht mithalten kann *g* Im Grunde werden hier die Daten für den Proxy vorbereitet. Das Object lo_controller bekommt die XML Nachricht und das Business System zugeschoben (hier wird der SLD name des Businessystems verwendet). Die Tabelle lt_parameters enthält dann die Parameter für den Proxy selbst.
4. Proxy aufrufen
Im letzten Schritt wird dann der Proxy gerufen. Proxytypisch komplett dynamisch
:
Zuerst den methoden namen zusammenbasteln:
| Code: |
| CONCATENATE lo_registry->object_name lo_registry->object_name1 INTO l_method SEPARATED BY '~'. |
und dann den dynamischen call mit unserer parametertabelle:
| Code: |
CALL METHOD (lo_registry->implementing_class)=>(l_method)
PARAMETER-TABLE
lt_parameters. |
Der Rest ist Errorhandling. Um so allgmein wie möglich zu bleiben fange ich hier alle Fehler zu zur cx_root Fehlerklasse ab.
Eine Letzte Anmerkung habe ich noch: Ihr solltet euch nicht wundern, wenn dieser Report keine Eintrag in der SXMB_MONI hinterlässt. Ich hab mich hier nur auf das wesentliche beschränkt
Viel Spaß noch!
Gruß Azreal
| Code: |
DATA: lv_error TYPE string VALUE 'success ;)'.
DATA: lo_exception TYPE REF TO cx_root.
DATA: l_conv TYPE REF TO cl_abap_conv_out_ce,
l_xml_string TYPE string,
l_xml_xstring TYPE xstring.
***************** 1. * XML-String erstellen **************
CONCATENATE l_xml_string '<?xml version="1.0" encoding="utf-8"?>' INTO l_xml_string.
CONCATENATE l_xml_string '<ns1:XYZ xmlns:ns1="http://..." xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' INTO l_xml_string.
CONCATENATE l_xml_string '</ns1:XYZ>' INTO l_xml_string.
* XML-String in raw mappen
l_conv = cl_abap_conv_out_ce=>create( encoding = 'UTF-8' ).
l_conv->write( data = l_xml_string ).
l_xml_xstring = l_conv->get_buffer( ).
***************** 2. * XML 2 ABAP Mapper **************
DATA: lt_send_bindings TYPE abap_trans_resbind_tab,
ls_binding TYPE abap_trans_resbind,
ls_parameter TYPE abap_parmbind,
lt_parameters TYPE abap_parmbind_tab.
TYPES: BEGIN OF rmdata,
bindings TYPE abap_trans_resbind_tab,
stylesheet TYPE cxsltdesc,
END OF rmdata.
DATA: ls_rmdata TYPE rmdata,
lt_signature TYPE sproxsigtt,
lo_xslt TYPE REF TO cl_proxy_stylesheet_runtime,
lo_registry TYPE REF TO cl_proxy_inbound_registry,
lv_receiver TYPE prx_srvc.
FIELD-SYMBOLS: <sig> TYPE sproxsig.
* Namespace des empfangenden Interfaces
lv_receiver-interface-namespace = 'XYZ_interface_namespace'.
* Empfangendes interface
lv_receiver-interface-name = 'XYZ_interface_name'.
TRY.
TRY.
* Registry object interface aus repository ziehen.
lo_registry = cl_proxy_inbound_registry=>create_from_ifr_name( p_interface = lv_receiver-interface ).
* Stylesheet vom Proxy ziehen.
lo_xslt = cl_proxy_stylesheet_runtime=>create_from_method(
p_object = lo_registry->object
p_obj_name = lo_registry->object_name
p_method = lo_registry->object_name1
p_extended_xml_handling = '').
IF lo_xslt->check_timestamp( ) = ''.
* ABAP 2 XML mapping generieren
lo_xslt->generate( ).
ENDIF.
ls_rmdata-stylesheet = lo_xslt->abap2xml_name.
* initialisieren der ABAP Struktur
lt_signature = lo_xslt->get_signature( ).
LOOP AT lt_signature ASSIGNING <sig>.
ls_binding-name = <sig>-param.
CREATE DATA ls_binding-value TYPE (<sig>-typename).
IF <sig>-decl = sprox_const_dir_importing.
APPEND ls_binding TO lt_send_bindings.
ELSEIF <sig>-decl = sprox_const_dir_exporting.
APPEND ls_binding TO ls_rmdata-bindings.
ELSEIF <sig>-decl = sprox_const_dir_changing.
APPEND ls_binding TO lt_send_bindings.
APPEND ls_binding TO ls_rmdata-bindings.
ENDIF.
ls_parameter-name = <sig>-param.
ls_parameter-value = ls_binding-value.
INSERT ls_parameter INTO TABLE lt_parameters.
ENDLOOP.
* XML auf ABAP mappen
CALL TRANSFORMATION (lo_xslt->xml2abap_name)
SOURCE XML l_xml_xstring
RESULT (lt_send_bindings).
CATCH cx_root.
lv_error = 'Unable to transform XML'.
ENDTRY.
***************** 3. * Senderparty festlegen **************
TRY.
DATA: lo_controller TYPE REF TO if_ai_proxy_controller.
CLASS cl_ai_factory DEFINITION LOAD.
CLASS cl_ai_posting_controller DEFINITION LOAD.
lo_controller = cl_ai_posting_controller=>create_controller( ).
* XML anh㭧en
lo_controller->set_input_payload( l_xml_xstring ).
* Name des empfangenden Systems setzten
* Empf㭧ersystem festlegen (SLD_NAME)
lv_receiver-bsn_system = 'SLD_NAME'.
lo_controller->set_sender_service( lv_receiver ).
* Controller in parameterliste hinzufügen
DATA: lo_appl_controller TYPE REF TO if_ai_posting_controller.
ls_parameter-name = 'CONTROLLER'.
lo_appl_controller ?= lo_controller.
GET REFERENCE OF lo_appl_controller INTO ls_parameter-value.
INSERT ls_parameter INTO TABLE lt_parameters.
CATCH cx_root.
lv_error = 'Unable to fill controller'.
ENDTRY.
***************** 4. * Proxy aufrufen **************
TRY.
DATA: l_method TYPE string.
* Proxy aufrufen
CONCATENATE lo_registry->object_name lo_registry->object_name1 INTO l_method SEPARATED BY '~'.
CALL METHOD (lo_registry->implementing_class)=>(l_method)
PARAMETER-TABLE
lt_parameters.
CATCH cx_root INTO lo_exception.
* Problem bei der Verarbeitung:...
DATA: lv_order_fault TYPE REF TO cx_sus_order_fault.
DATA: lv_fult TYPE REF TO cx_sy_no_handler.
DATA: test TYPE REF TO cx_root.
FIELD-SYMBOLS: <lv_test> TYPE REF TO cx_root.
ASSIGN lo_exception->previous TO <lv_test>.
lv_order_fault ?= <lv_test>.
lv_error = lv_order_fault->standard-fault_text.
ENDTRY.
CATCH cx_root.
ENDTRY.
WRITE: lv_error. |