
ADT - My IDE Actions
Eigene Funktionen in den ABAP Development Tools schreiben? Kein Problem mehr mit den IDE Actions im Standard und ganz ohne Java.
Inhaltsverzeichnis
In diesem Artikel gehen wir auf die neuen Features der IDE Actions ein und entwickeln selbst eine Funktion, um verschiedene Objekte im System zu erzeugen, mit denen wir regelmäßig arbeiten. Aber erst einmal Schritt für Schritt, um was es eigentlich geht.
Einleitung
Im ABAP Environment steht seit dem Release 2502 nun die IDE Actions zur Verfügung, dabei handelt es sich um ein komplettes Framework, um eigene Aktionen und Inhalte in den ABAP Development Tools zu entwickeln. Dabei erfolgt die Umsetzung nicht in Java, sondern direkt auf dem Applikationsserver in ABAP, was es für uns als ABAP Entwickler um einiges einfacher macht. Damit kannst du Aktionen implementieren, die eine Autovervollständigung machen, Objekte generieren, Daten abfragen und vieles mehr.
Start
Zuerst einmal müssen wir das System und die erste Aktion vorbereiten, bevor wir mit der eigentlichen Entwicklung starten können.
Berechtigung
Bevor wir allerdings in die Entwicklung einsteigen, kann es sein, dass wir erst noch Berechtigungen für die Entwicklung benötigen. Dafür gibt es einen neuen Business Catalog "Development - IDE Action Implementation" (SAP_A4C_BC_DEV_AIA_PC), erst dann können wir im System IDE Actions anlegen.
IDE Action
Haben wir dann alle Berechtigungen, können wir unsere Aktion im System anlegen. Dazu gehen wir auf das entsprechende Paket und legen über das Kontextmenü "New -> Other ABAP Repository Object" eine IDE Aktion an. Neben Namen und Beschreibung müssen wir keine weiteren Details berücksichtigen.
Nachdem wir die Aktion im System angelegt haben, befüllen wir dann das Formular mit den entsprechenden Informationen, um die Aktion und die UI zu erstellen. Mehr Details findest du im nächsten Kapitel.
My IDE Actions
In diesem Kapitel werden wir uns die erste IDE Action für "Create new class" anschauen, dabei geht es um die Generierung von Artefakten für eine Klasse. Dabei kann neben der Klasse auch das entsprechende Interface, die Factory und ein Injector generiert werden. Damit sind alle Artefakte vorhanden, um die Lösung zu entkoppeln und testbar zu machen.
Aufbau
Ziel ist es, dass wir die Aktion auf einem Paket durchführen können und wir einen Eingabedialog erhalten. Dort sollen möglichst schon einige Informationen vorgeblendet sein, die wir aus dem Kontext des Pakets erhalten. Ergänzen wir dann den Namen, sollen aktuelle Vorschläge zu diesen Namen generiert werden. Im Anschluss sollen die Artefakte generiert werden und dem Paket zugeordnet werden, sowie auch dem Transport.
Generator
Im Projekt verwenden wir einen Generator für die ABAP Artefakte, den wir hier erst einmal nicht genauer beschreiben werden. Grundsätzlich übergeben wir dem Generator unsere Konfiguration, damit er die Objekte und Zusammenhänge generieren kann. An der Konfiguration richtet sich am Ende auch unsere UI aus.
TYPES:
BEGIN OF setting,
prefix TYPE prefix,
name TYPE sxco_ao_object_name,
description TYPE if_xco_cp_gen_intf_s_form=>tv_short_description,
transport TYPE sxco_transport,
package TYPE sxco_package,
interface TYPE sxco_ao_object_name,
class TYPE sxco_ao_object_name,
factory TYPE sxco_ao_object_name,
injector TYPE sxco_ao_object_name,
END OF setting.
UI
Im ersten Schritt benötigen wir einen Action Dialog, um dem Anwender die Eingabe zur ermöglichen. Dazu können wir über den Link in der IDE Action eine neue Klasse erzeugen. Diese implementiert das Interface IF_AIA_SD_ACTION_INPUT, hier wird aber nur die Methode CREATE_INPUT_CONFIG definiert, die anderen drei Methoden können optional implementiert werden. Als Struktur für die Eingabe definieren wir einen öffentlichen Typen in der Klasse, über die ABAP Docs können wir den Feldern bestimmte Eigenschaften geben. Eine Liste der Eigenschaften findest du in der Dokumentation, wobei bestimmte Eigenschaften über die Konfiguration gesetzt werden.
TYPES:
"! <p class="shorttext">Create new class</p>
BEGIN OF input,
"! $required
"! $maximum 30
package TYPE sxco_package,
"! $required
"! $maximum 20
transport TYPE sxco_transport,
"! $required
"! $maximum 10
prefix TYPE zif_mia_object_generator=>prefix,
"! $required
"! $maximum 24
name TYPE sxco_ao_object_name,
"! $required
"! $maximum 50
description TYPE if_xco_cp_gen_intf_s_form=>tv_short_description,
"! $required
"! $maximum 30
class TYPE sxco_ao_object_name,
"! $maximum 30
interface TYPE sxco_ao_object_name,
"! $maximum 30
factory TYPE sxco_ao_object_name,
"! $maximum 30
injector TYPE sxco_ao_object_name,
END OF input.
Über die Information Factory legen wir uns eine Konfiguration an, damit können wir viele zusätzliche Eigenschaften und Verhalten definieren. So setzen wir das Paket auf Anzeige und erzeugen einen Side Effect auf Präfix und Name, damit die abhängigen Informationen bei der Eingabe aktualisiert werden.
DATA input TYPE input.
DATA(configuration) = ui_information_factory->get_configuration_factory( )->create_for_data( input ).
configuration->get_element( `PREFIX` )->set_sideeffect( after_update = abap_true ).
configuration->get_element( `NAME` )->set_sideeffect( after_update = abap_true ).
configuration->get_element( `PACKAGE` )->set_read_only( ).
RETURN ui_information_factory->for_abap_type( abap_type = input
configuration = configuration ).
Default Werte
Im nächsten Schritt wollen wir einige Werte in der Eingabe auf Standard setzen. Dazu erweitern wir die Input Klasse, wo der Dialog erzeugt wird. Aus dem Kontext Objekt holen wir uns die aktuelle Fokus Ressource, was laut Definition das Paket sein sollte. Darüber gelangen wir an den Namen des Pakets. Anhand des Pakets können wir das Präfix ableiten, also entweder Y, Z oder ein Namespace mit Slash. Ist das Paket neu, können wir über den Sperreintrag und die XCO Klasse den Transport nachlesen und mit übernehmen.
IF context IS BOUND.
DATA(focused_object) = context->get_focused_resource( ).
input-package = focused_object->get_name( ).
input-prefix = zcl_mia_strings=>get_prefix_from_package( input-package ).
input-transport = get_transport_for_object( input ).
ENDIF.
Für den Transport verwenden wir die XCO Klasse XCO_CP_ABAP_REPOSITORY, darüber können wir das Paket einlesen und im Bereich Änderungen zum Objekt eine Sperre ermitteln und den Transport ableiten. Sollte das Objekt aktuell keine Sperre haben, müssen wir eine Ausnahme abfangen und setzen den Transport auf Initial.
xco_cp_abap_repository=>package->for( input-package )->if_xco_cts_changeable~get_object( )->get_lock( )->get_transport( ).
Um die Aktion in Eclipse zu starten, können wir ein Paket im Project Explorer markieren und mit STRG + ALT + R den Action Dialog starten, wo nun unsere IDE Action verfügbar sein sollte.
Wählen wir nun unsere Aktion aus, werden wir mit unserem definierten Dialog begrüßt. Die Felder haben das entsprechende Verhalten und die Defaultwerte sind sauber gesetzt.
Side Effects
Im nächsten Schritt wollen wir eine Aktualisierung auf dem Dialog erzeugen. Immer wenn wir das Präfix oder Namen anpassen, dann sollen die Namen der Objekte dynamisch angepasst werden. Über die Side Effects können wir diesen Punkt realisieren. Dazu müssen wir eine zusätzliche Klasse anlegen, die das Interface IF_SD_DETERMINATION implementiert. In der RUN Methode können wir zum Beispiel auch überprüfen, in welcher Phase wir uns befinden. Über das Model lesen wir die aktuellen Daten des Popups ein und ermitteln im Anschluss die neuen Namen. Das Ergebnis übergeben wir an RESULT.
DATA popup_data TYPE zcl_mia_newclass_input=>input.
IF determination_kind <> if_sd_determination=>kind-after_update.
RETURN.
ENDIF.
model->get_as_structure( IMPORTING result = popup_data ).
determine_names( CHANGING popup_data = popup_data ).
result = popup_data.
In der UI Klasse müssen wir noch die Methode GET_SIDE_EFFECT_PROVIDER ausprägen, diese befindet sich im Interface, wird standardmäßig, aber nicht angelegt. Über den Side Effect Provider geben wir dann unsere Klasse als neue Instanz zurück.
RETURN cl_sd_sideeffect_provider=>create( determination = NEW zcl_mia_newclass_side_effect( ) ).
Wir können uns nun das Verhalten auf dem Popup anschauen. Der Name des Objekts wird immer nach Eingabe angepasst. Um so länger der Standardname ist, desto kürzer fällt der Zusatz aus. Es werden aber mindestens zwei Zeichen benötigt.
Aktion
Nach dem das UI und das Verhalten definiert wurde, müssen wir die eigentliche Aktion ausprägen. Unsere Klasse benötigt dazu eine Implementierung des Interfaces IF_AIA_ACTION. In der RUN Methode lesen wir uns dann über das CONTEXT Objekt die Daten der UI ein, um damit arbeiten zu können.
DATA popup_data TYPE zcl_mia_newclass_input=>input.
TRY.
context->get_input_config_content( )->get_as_structure( IMPORTING result = popup_data ).
CATCH cx_sd_invalid_data.
ENDTRY.
Die Daten und Einstellungen übergeben wir dann an den Generator. Das Ergebnis können wir dann über den HTML Konverter in eine Ausgabe umwandeln und übergeben es an das HTML Popup, damit der Anwender eine Meldung erhält.
DATA(action_result) = cl_aia_result_factory=>create_html_popup_result( ).
action_result->set_content( html_output ).
result = action_result.
Ergebnis
Nach dem wir nun die Aktion implementiert haben, schauen wir uns einmal die IDE Aktion an und lassen uns ein paar Artefakte generieren. Den Dialog befüllen wir wie folgt:
Da wir uns keinen Injector anlegen wollen, löschen wir den Eintrag, dieser ist auch kein Pflichtfeld. Die anderen Artefakte wollen wir uns generieren lassen. Dann können wir den Lauf starten, die Generierung wird etwas an Zeit in Anspruche nehmen.
Sind die Objekte angelegt, erhalten wir unser Ergebnis und falls es Fehlermeldungen geben sollte, werden diese ebenfalls hier ausgegeben. Neben den Objekten finden wir auch den zugeordneten Transport im System.
Zum Abschluss prüfen wir das Paket, ob alle Objekte auch erzeugt wurden. Diese haben wir auch gleich nach der Generierung aktivieren lassen, sodass die Konsistenz und Fehlerfreiheit gewährleistet ist.
Open Source
Wir stellen die neuen Aktionen als Open Source Projekt zur Verfügung, sodass du diese auch in deinem System verwenden kannst. Weitere Informationen und das Projekt findest du im GitHub Repository. Da aktuell eine Sicherung der IDE Actions im Git nicht möglich ist, muss im Nachgang die Action manuell im System angelegt werden.
Fazit
Die Entwicklung von IDE Aktionen in den ABAP Development Tools geht sehr gut von der Hand und die Dokumentation von SAP ist überraschend gut geworden, sodass man fast alle Informationen für die Entwicklung findet. Deshalb auch ein Lob an die Kollegen für die vollständige Auslieferung im ersten Schritt. Hast du Interesse an den IDE Actions, dann probiere sie einfach einmal aus.
Quelle:
SAP Help - Working with IDE Actions
ABAP Environment Roundtable #20