Heiner KückerJSP WorkFlow Engine Control and Command |
|
Home Java-Seite Bit Packed Array ASM Improved heterogene Map, HMap Constraint Code Generator JSP WorkFlow PageFlow FlowControl Page Flow Engine Web Flow Engine Control_and_Command JSP_Spreadsheet Code-Generator für Option-Either-Stil in Java verbesserter Comparator Fluent-Interface Code-Generator auf Basis einer Grammatik Visitor mit Multidispatch for-Schleife mit yield-return Kognitions-Maschine semantisches Netz Domain Parser Codegenerator_für hierarchische Datenstrukturen Expression_Engine Formula_Parser Thread Preprocessor State Transition Engine AspectJ Java_Explorer DBF_Library Kalender_Applet SetGetGen BeanSetGet CheckPackage LineNumbers GradDms Excel-Export StringTokenizer JspDoc JspCheck JSP-Schulung Java Server Pages Struts Ascii-Tabellen- Layouter Ascii-Baum- Layouter Ascii-Art-Fluss- Diagramm- Parser AsciiArt AssignmentMatrix Layouter StringSerial Silbentrennung JDBC_Schlüssel- Generierung bidirektional/ unidirektional gelinkte Liste Java_Sitemap Generator XmlBuilder RangeMap StringFormatter VersionSafe XCopy JTextField CommandLine- ParamReader Bitmap-Grafik MultiMarkable- Buffered- InputStream JavaCache JdomUtil CollectionUtil XML Really Pull Parser Log-Filter Remote-Protokoll Sudoku-Generator Delegation statt Mehrfachvererbung Disjunct Interval Set WebCam_Demo Weiterentwicklung_Java Alaska-XBase++-Seite Projekte Philosophien Techniken Konzepte Sudoku Kontakt / Impressum Links SiteMap Letzte Aktualisierung: 14.05.2005 |
Control and Command
Fluss-Steuerung (WebFlow) für JSP-Anwendungen Demo-Applikation auf www.control-and-command.de Veröffentlicht im Java-Magazin 03.2003, Seite 81 - 88, (web apps Fluss-Steuerung für JSP-Anwendungen) News-Update Java-Magazin 03. Dezember 2004 Das Framework Control and Command ist eine Fluss-Steuerung für JSP- und Servlet-Applikationen. Es beruht auf einer Java/C-ähnlichen Steuersprache und besitzt Strukturen (Schleifen, Verzweigungen), Befehle, Unterprogramme (Prozeduren, Funktionen), lokale Variable und Parameter (per value/reference). The Framework Control and Command is an JSP FlowControl Workflow PageFlow Engine for JSP (Java Server pages) and Servlet-Applications. It's based on a own Scriptlanguage and has Struktures, Instructions, Subprogramms, lokal Variabels and Parameters (per value or per reference). The Compiler and the Runtimeenvironment for the Flow Language is completely written in Java. The page flow and additional features are completely written in the script langauge. Es vollzieht die Entwicklung der EDV von der GOTO-Programmierung zur strukturierten Programmierung für JSP-Applikationen nach (Synergie-Ansatz). Dabei entspricht die konventionelle Herangehensweise mit forward() und redirect() dem GOTO-Ansatz. Das Action-Mapping analog Struts und anderer Web- Frameworks nach dem Prinzip eines endlichen Zustandsautomaten (Finite State Machine) ist demgegenüber wesentlich unübersichtlicher und bietet weniger Möglichkeiten. Das Wiederaufnehmen des Flusses nach dem Absenden des erzeugten HTML und dem erneuten Request des Browsers habe ich unter das API des CnC-Frameworks gedrückt. Dadurch ist das Hinnehmen (Resignieren vor) einer ereignisorientierten Realisierung, die durch das Postulieren des MVC-Patterns zur Lösung erhoben wird, nicht mehr notwendig. Web-Applikationen können wie modale Terminal- oder DOS-Applikationen geschrieben werden. Auf dieser Basis könnte MVC (Ereignisorientierung) auf einer nächsthöheren Ebene eine Rolle spielen, wenn die Browser Möglichkeiten zur Realisierung richtiger GUI-Applikationen durch das Aktualisieren von Feldinhalten, Tabellenzellen und Menüs, Absenden von Button- und Change-Ereignissen und allen weiteren GUI-Notwendigkeiten (Callback-Hooks, Remote-Referenzen) zusätzlich zum kompletten Neuaufbau einer HTML-Seite böten. Ausgehend von den bekannten Prinzipien der strukturierten Programmierung, wie Schleifen, Verzweigungen und Unterprogramme, ist die Realisierung als Compiler mit einer dynamisch erzeugten internen Befehlstabelle relativ naheliegend. Aktuell sind ähnliche Frameworks, teilweise in anderen Programmiersprachen wie Smalltalk (SeaSide), als Continuation-Servers bekannt. Dabei benutzt CnC keine nativen Continuations in Java, sondern eine eigene Script-Sprache. Ein Programm könnte folgendermassen aussehen: procedure daterange() while ( true ) // Endlos-Schleife { session:CNC_MESSAGE_KEY := "Bitte Datum von 1.1.2005 bis 31.12.2005 eingeben"; jsp ( "/date/date.jsp" ); // hier bleibt der Fluss stehen, bis ein Request vom Browser zurückkommt session:date := strToDate( request:date ) ; // eingegebenes Datum zwischenspeichern if ( session:date >= strToDate( "1.1.2005" ) ) // if date >= 01.01.2005 { if ( session:date <= strToDate( "31.12.2005" ) ) // if date <= 31.12.2005 { session:CNC_MESSAGE_KEY := "Datum ist korrekt" ; // Setzen Meldung break ; // Schleife beenden } // end if } // end if } // end while } // end procedure daterange Architektur CnC =============== Kompilieren: ------------ Steuerdatei flow.cnc | wird gelesen von | FlowControlParser | erzeugt | FlowControlTable ---- enthält ---- > FlowControlInstruction Ablauf: ------- +------- > FlowControl --- benutzt --- > FlowControlTable --- enthält --- > FlowControlInstruction | | | | startet ruft | | | | JSP +--- > ActionMethoden (z.B. CncDemoDefaultActions) | | | ruft (Browser HTTP-Request) | | | CncServlet --- erweitert durch --- > Applikations-Servlet (z.B. CncDemoServlet) | | | übergibt die Steuerung an | | +-----------+Demo-Applikation auf www.control-and-command.de WAR-File für Tomcat5 unter JDK 1.4 Download cncdemo.war Das war-File können Sie in das Verzeichnis TOMCAT_HOME/webapps kopieren. Tomcat (re)starten. Ansehen mit http://localhost:8080/cncdemo . Source-Code Download der Quelldateien Cnc.zip Installation: Entpacken in Verzeichnis Ihrer Wahl (z.B. C:\CnC) Kompilieren mit ANT (build.bat oder build.xml) Start im Tomcat 5 mit http://localhost:8080/cncdemo Syntax Steuer Datei für UltraEdit Zum angenehmen Editieren der Steuerdatei flow.cnc habe ich für den UltraEdit (mein bevorzugter Editor neben der Eclipse, hat einen super Spaltenmodus) eine Sequenz für die Wortlistendatei (standardmäßig "WORDFILE.TXT") erstellt. Sie müssen die Sequenz in die Wortlistendatei (standardmäßig "WORDFILE.TXT") Ihrer UltraEdit-Installation einfügen. Wichtig ist dabei, dass die Nummer in der ersten Zeile (L11) die exakte laufende Nummer in der Reihenfolge der Syntax-Definitionen angibt. Download der Syntax Steuer Datei WORDFILE.TXT für UltraEdit. Anleitung Control and Command ============================= Unterstützung ------------- Vielen Dank an die im folgenden aufgeführten Privatpersonen, durch deren Unterstützung CnC entstehen konnte: Ingo Ciechowski (CIS-Computer GmbH) Ralf Schramm (Deutsche Bahn AG) Suresh David Tucker (Deutsche Bahn AG) Allgemeines ----------- Control and Command ist eine Lösung zur Ablaufsteuerung von Web- Applikationen. Herkömmliche JSP-Servlet-Applikationen realisieren ihren Steuerfluss in forwards, form-actions und link-hrefs in einer Art GOTO-Programmierung. Besser ist die Vorgehensweise von Struts mit einer zentralen Steuerdatei struts-config.xml mit dem zentralen Hinterlegen der Navigation als Mapping-Tabelle im Tag action. Dieses Action-Mapping ist aber noch relativ unübersichtlich. In langen Spaziergängen habe ich die Idee für mein CnC entwickelt (zugegeben, kein besonders phantsievoller Name, Liquid oder so wäre vielleicht besser, ich weiss aber nicht wie es mit dem Markenschutz ist). Da das HTTP-Protokoll statuslos ist, muss der Status irgendwo zwischengespeichert werden. Ich habe überlegt, dass ein Prozessor (in Rückbesinnung an meine Z80- und 8086- Assemblerzeit) als Status nur seinen Program- Counter und seine Register hat. Diese relativ geringe Informationsmenge könnte man zum Browser und von dort aus wieder zurücksenden (Hidden-Fields, URL-Encoding). Die Session enthält in diesem Falle die Informationen analog dem Hauptspeicher. Der Steuerfluss wird komplett in CnC-Language aufgeschrieben und die JSPs sowie Actions returnen lediglich zur zentralen Steuerkomponente. Die Steuerkomponente entscheidet, welche JSP oder Action als nächstes aufgerufen wird. Mit CnC ist es möglich, eine JSP-Servlet-Applikation wie eine modale Terminal(DOS)-Applikation zu schreiben. -alter Zustand Im JSP (Link oder Form-Action) und im Servlet (forward) selbst ist das Sprungziel gespeichert. Sehr unflexibel und schlecht zu warten. -Jakarta-Struts Mapping symbolische Namen für Actions Actions können unter unterschiedlichen logischen Namen und mit differierenden Sprungzielen deployt werden. keine logischen Namen für Views (JSP). wesentlich besser -Problem Nutzung eines JSP zum Editieren oder Hinzufügen DB-Record edit-Button --> getRecord --+ +--> UPDATE | +-----+ | +-->| JSP |--+ | +-----+ | add -Button --> initForm ---+ +--> INSERT Hilfskonstrukte über request-Parameter oder implizite Annahmen (wenn Record-ID leer, dann INSERT). Struts hilft hier nicht. -Basis der Idee Synergie -Zurück zu Wurzeln -wie funktioniert ein Prozessor PC-Programmcounter Register Flags RAM -Programmabarbeitung ab Reset ein Befehl ADD muss auch nicht wissen, wohin er zurück-/weiter-springen muss -mein Konzept Control and Command +------+ | Menu |<------------------+ +------+ | | | | +--------------+ +------+ | | | | +--------+ +------+ | |ListView|<--+ | Form | | +--------+ | +------+ | | | | | +-->Top----+ +------+ | | | |Action| | +-->PgUp---+ +------+ | | | | | +-->PgDn---+ +--------------+ | | +-->Bott---+ +----------------+ Commands | Control | +-------+ | |------------>| JSP | | | +-------+ | | | | |<----------------+ | | | | +--------------+ | |------------>|Backend-Action| | | +--------------+ | | | | |<----------------+ | | | | | | | | +----------------+ Command-Table (applikationsweites Singleton) +--------+------------------------------+ |Adress | Command-Name | +--------+------------------------------+ | 0 | menu.jsp | +--------+------------------------------+ +------>| 1 | Goto IF <xxx> 5 | | +--------+------------------------------+ | | 2 | Goto IF <xxx> xx | | +--------+------------------------------+ | | 3 | Goto IF <xxx> xx | | +--------+------------------------------+ | | 4 | Goto 0 | | +--------+------------------------------+ +-----------------+ | | 5 | ListeGetAction | | Program-Counter |------+ +--------+------------------------------+ +-----------------+ | 6 | listview.jsp | Programm-Counter wird +--------+------------------------------+ in Session abgespeichert | 7 | Goto IF <Up-Button> 13 | (später sehen wir, daß es +--------+------------------------------+ damit ein Problem gibt) | 8 | Goto IF <Dn-Button> 15 | +--------+------------------------------+ | 9 | Goto IF <Edit-Button> 17 | +--------+------------------------------+ | 10 | Goto IF <Add-Button> | +--------+------------------------------+ | 11 | Goto IF <Del-Button> | +--------+------------------------------+ | 12 | Goto IF <Ret-Button> 0 | +--------+------------------------------+ | 13 | PageUpAction | +--------+------------------------------+ | 14 | Goto 6 | +--------+------------------------------+ | 15 | PageDnAction | +--------+------------------------------+ | 16 | Goto 6 | +--------+------------------------------+ | 17 | RecordGetAction | +--------+------------------------------+ | 18 | formedit.jsp | +--------+------------------------------+ | 19 | Goto IF <Break-Button> 6 | +--------+------------------------------+ | 20 | RecordSaveAction | +--------+------------------------------+ | 21 | Goto 6 | +--------+------------------------------+ | 22 | | +--------+------------------------------+ | .. | und so weiter | +--------+------------------------------+ +----------------+ Commands | Control | Parameter(z.B. add/edit) +-------+ | |--------------------------------->| JSP | | | +-------+ | | | | |<-------------------------------------+ | | Ergebnis-Flags | | | | | | Parameter (z.B. SELECT-Cond) +--------------+ | |--------------------------------->|Backend-Action| | | +--------------+ | | | | |<-------------------------------------+ | | Ergebnis-Flags | | +----------------+ Der virtuelle Prozessor sollte Register besitzen. Dadurch ist die Codierung von Flags in Registern und das Halten komplexerer als nur binärer Stati möglich. Wegfall Flags binäre Codierung Flag1 = 1 Flag2 = 2 Flag3 = 4 State = Flag2 + Flag3 +-+-+-+-+-+-+-+-+-+ |0|0|0|0|0|0|1|1|0| +-+-+-+-+-+-+-+-+-+ | | | | | +------ Flag1 | +-------- Flag2 +---------- Flag3 Was sollte die Control-Komponente können: Goto-Programmierung vs. strukturierte Prog Formulierung der Steuerstruktur -like 4GL -XML -graf. Flussdiagramm-Tool (Visio) -Graf. Tool zur strukturierten Prog Unterprogramme Parameterpassing (per value, per reference) lokale variablen (compile-time-scope, runt-time-scope) Problem stateless Analogie zu Win-Programm Problem Back-Button und Strg-N Status (Flags und register) in Page(Session) speichern Verschlüsselung Status (Synchronisations-Token) Komponenten Parser für Control und Erzeugung Control-Table Control-Servlet Das Framework CnC spielt die Rolle einer zentralen Fluss-Steuer- Komponente, die von einer Steuersprache, ähnlich einem primitiven Basic, gespeist wird. Aufbau einer CnC-Applkation --------------------------- Schreiben des Flusses in flow.cnc (Name lässt sich umkonfigurieren) Eigenes zentrales Servlet vom CncServlet ableiten (analog zu CncDemoServlet) (Eintragen in web.xml) Erstellen der Action-Methoden (Controller) in entsprechenden Action-Klassen Schreiben Ihrer JSP´s (Views). Erstellen eigener Tags oder Benutzen verfügbarer Tag-Libs. Datenbank-Anbindung (nicht durch CnC unterstützt). Konfigurationsdatei web.xml --------------------------- CnC-Servlet: Hier tragen sie das zentrale Servlet ihrer Web-Applikation ein, das sie von de.cnc.CncServlet abgeleitet haben. <servlet> <servlet-name>cncaction</servlet-name> <servlet-class>de.cnc.CncDemoServlet</servlet-class> <init-param> ... hier folgen weitere Initialsierungsparameter Url-Pattern Eintrag in web.xml Konstante in cnc-servlet Das URL-Pattern *.cnc ist auf obiges Servlet cncaction gemappt, wodurch alle URIs, die mit .cnc enden, auf das zentrale Servlet umgeleitet werden. <servlet-mapping> <servlet-name>cncaction</servlet-name> <url-pattern>*.cnc</url-pattern> </servlet-mapping> Steuerdatei flow.cnc -------------------- Der Steuerfluss wird in einer Script-Datei mit dem Default-Namen flow.cnc codiert. In der Konfigurationsdatei der Web-Applikation web.xml kann ein alternativer Name festgelegt werden: <init-param> <param-name>flowfile</param-name> <param-value>flow.cnc</param-value> </init-param> Der alternative Name wird in der init-Methode der Klasse FlowControl gelesen. Der Pfad ergibt sich aus dem WEB-INF Verzeichniss der Webapplikation: /WEB-INF/dateiname.cnc Flow-Control-Mode ----------------- Für die Fluss-Steuerung gibt es zwei Möglichkeiten, Browser- Leading oder Session-Leading. Beim Browser-Leading wird der Status des FlowStack zum Browser gesendet und von ihm wieder zu Server gesendet. Das Benutzen des Back-Buttons oder des Öffnen eines neuen Browser-Fensters ist erlaubt. Der vom Browser gesendete Status bestimmt den Fluss- Status. Beim Session-Leading wird lediglich eine Prüfummer zum Browser gesendet, beim Auftreten einer invaliden Prüfnummer wird der aktuelle Fluss abgebrochen und mit einer Fehlermeldung zur Adresse 0 gesprungen. Ein Mechanismus zum Informieren der Applikation, dass ein CnC-Status-corrupt-Event aufgetreten ist, wird noch eingebaut. Die Betriebsart kann über die Methoden FlowControl#setBrowserLeading() FlowControl#getBrowserLeading() gesetzt und abgefragt werden. Alternativ ist die Einstellung in web.xml möglich: <init-param> <param-name>flowleading</param-name> <param-value>browser(default) oder session</param-value> </init-param> Problem mit der Form -------------------- Links können bestimmte URIs ansteuern. Paramter können mit dem Anhängen eines Strings "?name=value" an die URI mitgegeben werden. Dabei werden keine Formulardaten mit übertragen. Forms können nur eine URI ansprechen. Parameter können über Hidden-Fields mitgegeben werden. Welcher Button innerhalb der Form gedrückt wurde, muss über die Request-Parameter ermittelt werden. Dabei muß nach HTML-Buttons und Image-Buttons unterschieden werden. Dabei werden die in der submitteten Form (pro HTML-Seite sind mehrere möglich) enthaltenen Formulardaten mit übertragen. <form action="ControlServlet?controlstatus=003" method="post"> Eine Form ist notwendig um Formulardaten an den Server senden zu können. Eine Form kann nur eine einzige Action ansteuern, egal welcher Submit-Button gedrückt wird. Der Action-URI können weitere Parameter angehängt werden. <input type="text" value="initialwert" size="100"> Ein Formularfeld muß den Anfangswert (value="...") aus der Formularbean bekommen. Über den Namen kann das ControlServlet den eingegeben Wert in die Formularbean einparsen. <input type="submit" name="name" value="value"> Beim Betätigen des Submit-Button´s wird die Action-URI der Form angesteuert. Unterschiedliche Submit-Button´s können über Name und Value differenziert werden. Der Value ist dabei der Text auf dem Button (Aufpassen bei landesspezifischer Anpassung). <input type="image" name="Button" src="Abbrechen.gif" alt="Abbrechen"> Gif-Buttons wirken wie Submit-Buttons und erlauben auch Differenzierung über Name und Value Der Name wird als name.x und name.y im Request abgelegt, weshalb über alle Parameter-Namen im Request mit String.startsWith() nach dem Namen gesucht werden muß. <input type="button" JavaScript-Button noch nacharbeiten <a href="ControlServlet?controlstatus=003&action=MAINMENU">Zurück zum Hauptmenü</a> Beim Betätigen eines Links in der Form werden die Formularwerte nicht in den request mitgeliefert. Der Link-URI können weitere Parameter angehängt werden. </form> GOTO-Actions ------------ In Web-Applikationen werden oft Navigationsleisten verwendet. Diese ermöglichen das Aufrufen bestimmter Seiten unabhängig vom aktuellen Status der Web-Applikation. Laufende Vorgänge werden abgebrochen und zur Zielseite verzweigt. Damit solche globalen Links nicht an allen Stellen im Fluss von CnC (flow.cnc) codiert werden müssen, gibt es GOTO-Actions. GOTO-Actions werden in der excute-Methode der Klasse FlowControl ausgewertet. Dabei können Labels (Sprung-Marken) oder Prozeduren angesprungen werden. Das direkte Ansteuern von Prozeduren ist erlaubt, weil in einer Prozedur ein Teilbereich der Web-Applikation codiert sein kann. Beim Return aus diesen Prozeduren ist der Stack nicht mehr korrekt. Deshalb wird bei Return auf leeren Stack zur Adresse 0 ( erste Zeile in der Prozedur main) verzweigt. Hier sollte die Hauptseite (evtl. nach Login liegende Hauptseite) der Web- Applikation liegen. GOTO-Actions werden in Links und bei Buttons mit dem Prefix cnc_goto_ (hinterlegt in de.cnc.RequestKeys) gekennzeichnet. Damit es auch mit Image-Buttons funktioniert, werden angehängte ".x" und ".y" entfernt. Für die GOTO-Actions gibt es die CnC-Tags <cnc:hrefgoto <cnc:buttongoto <cnc:imagebuttongoto Verwendung von Custom-JSP-Tags ------------------------------ Zum Encoden des CnC-Status und des Session-Key für Links und Forms stehen spezielle Customer-Defined-Tags zur Verfügung. Um die Tags zu verwenden, muss in der jeweiligen JSP-Seite folgende JSP-Direktive stehen: <%@ taglib uri="/WEB-INF/cnc.tld" prefix="cnc" %> Links: Zum Encoding von Links steht das Href-Tag zur Verfügung. <cnc:href href="action"/>Link-Text</a> Forms: <cnc:form action="action"/> ... ... </form> Debugging: Das Debug-Tag gibt einen vorformatierten Text (siehe <pre>-Tag) mit den Zeilen aus der Fluss-Steuer-Datei flow.cnc aus. Die aktuelle Zeile wird hevorgehoben dargestellt. <cnc:debug/> Blättern: Zum Blättern stehen die Tags: <cnc:buttonfirstpage/> <cnc:buttonprevpage/> <cnc:buttonnextpage/> <cnc:buttonlastpage/> zur Verfügung. Weitere Tags für Blätter-Links und Blätter-Image- Buttons folgen noch. Die von diesen Tags abgesendeten Actions bzw. Request-Parameter werden im CncServlet als implizite Actions abgearbeitet und anschliessend zur Source-JSP zurückgekehrt. Zur Verwendung dieser Tags muss man lediglich vorher auf dem Session- Key CNC_LIST_KEY eine ArrayList ablegen. Weitere implizite Actions für MvUp, MvDn, Insert, Delete und Add für Listen baue ich noch ein. Implizite Actions ----------------- noch nicht fertig Input-Tags für Bean-Properties die keine Strings sind ----------------------------------------------------- Der Browser liefert alle Daten aus den HTML-Forms als Strings. In der Klasse de.cnc.util.BeanUtil Methode convertToClass erfolgt die Umwandlung der Strings aus dem Browser-Request in die gewünschte Zielklasse der Bean-Property. Hier ist der Ansatzpunkt zum Einarbeiten zusätzlicher Klassen und für die Internationalisierung (I18N). Unterdücken des Einparsens von Formular-Daten beim Betätigen des Abbrechen-Buttons ---------------------------------------------------------------------------------- Durch Mitsenden eines Request-Keys CNC_BUTTON_NO_PARSE ("cnc_buton_no_parse") kann das Einparsen in die Formular-Bean (Session-Key CNC_FORM_KEY) und Listen-Bean (Session-Key CNC_LIST_KEY) vermieden werden. <input type="submit" name="<%= de.cnc.RequestKeys.CNC_NO_PARSE %>" value="Abbruch"/> oder <cnc:formbreakbutton value="Abbruch"/> Der Vorteil dieser Option ist, dass für die Funktionalität "Abbrechen" kein extra Puffer für die Originalwerte (Editierpuffer) bereitgehalten werden muss. Die veränderten Werte werden beim Abbruch nicht eingeparst und können die Originalwerte nicht überschreiben. Implizite Session-Values ------------------------ Implizite Session-Values sind Schlüssel-Werte-Paare aus dem Request, die automatisch wieder in die entsprechenden Session-Keys zurückgeschrieben werden. Dadurch ist es nicht nötig, diese Werte mit session:setAttribute( request.getAttribute(...) ) oder mit einer Zuweisung in die Session zurückzuschreiben. Sie haben den Festen Prefix RequestKeys.CNC_SESSION_VALUE_PREFIX. Im <cnc:input>-Tag (JSP) wird der Prefix bei aktiviertem Attribut sessionvalue="true" vor den Namen gesetzt. Dieser Prefix wird beim Einparsen im CncServlet abgeschnitten. Die Adressräume der CnC-Sprache ------------------------------- Die CnC-Steuersprache unterstützt die Scopes der JSP-Servlet-Spezifikation request, session und application über entsprechende Prefixe der Variablen-Namen. Die Key´s der jeweiligen Map´s der JSP-Servlet-Applikation sind die Variablennamen der CnC-Sprache. CnC-Language | Java ------------------------------------+----------------------------------------------- request:param:Xyz (nur lesend) | request.getParameter( "Xyz" ); | request:attr:Xyz | request.getAttribute( "Xyz" ); request:attr:Xyz := <expr> | request.setAttribute( "Xyz" , <expr> ); | session:Xyz | session.getAttribute( "Xyz" ); session:Xyz := <expr> | session.setAttribute( "Xyz" , <expr> ); | application:attr:Xyz | application.getAttribute( "Xyz" ); application:attr:Xyz := <expr> | application.setAttribute( "Xyz" , <expr> ); | application:init:Xyz (nur lesend) | application.getInitParameter( "Xyz" ); | implizite Variable ------------------ cnc_button - der Name des betätigten Buttons cnc_button_index - der Index des Buttons in Tabellen (in einfachen Forms -1) cnc_link - Abfrage action="..." der HTML-FORM oder Link HREF="..." cnc_javascript_on - Abfrage, ob JavaScript eingeschaltet ist noch nicht fertig) cnc_no_validate - Abfrage, ob ein Button mit der Option validate=false" betätigt wurde Ausdrücke in der CnC-Language ----------------------------- Alle Bedingungen, Abfragen und Zuweisungen in den CnC-Statements werden durch meine Expression-Library realisiert. Sie erlaubt das Arbeiten mit den java.lang- Elementar-Typen, die üblichen Verküpfungs- und Zuweisungsoperatoren, Methoden- Aufruf per Reflection, Operationen mit Array´s, java.util.List und java.util.Map, Sequencen und einiges mehr. Für Zuweisungen benutze ich := statt einem einfachen = . Hat mir eben so besser gefallen. Zur Anwendung bitte die entsprechende WebSite und Online-Demo ansehen. Befehle für die Steuerdatei flow.cnc (CnC-Language) =================================================== Auflistung aller erlaubten Deklarationen und Befehle für flow.cnc ----------------------------------------------------------------- action ( <String-Expression mit dem Namen der Action> ); // Aufruf einer Action-Methode action ( "ActionClass#ActionMethod" ); // Action-Klasse und Action-Methode durch '#' (Hyphen) getrennt session:a := action( ... ); // Zuweisung des Rückgabewertes einer Action zu einer Variable (session:xxx oder application:xxx) break; call ( <String-Expression mit dem Namen der Procedure/Function> ); session:a := call ( <String-Expression mit dem Namen der Function> ); // Zuweisung des Rückgabewertes einer Function zu einer Variable // (session:xxx oder application:xxx) continue; // zum Anfang einer do oder while-Schleife springen do ( <bedingung, boolean-Expression> ) { <body> } // Schleife wird mindestens einmal durchlaufen und sonst solange Bedingung == true else { <body> } // die geschwungenen Klammern sind zwingend erfoderlich else if ( <bedingung, boolean-Expression> ) { <body> } // die geschwungenen Klammern sind zwingend erfoderlich function <procedure_name> ( <parameter> ) { <body> } // Function-Deklaration goto <label_bezeichner>; // Ansprung eines Labels in der main-Procedur zum Realisieren von Navigationslinks if ( <bedingung, boolean-Expression> ) { <body> } // die geschwungenen Klammern sind zwingend erfoderlich invalidate; // Session-Invalidate jsp ( <String-Expression mit dem Namen der JSP> ); // Anzeigen einer JSP, der Fluss stoppt hier und kann durch die CnC-Mechanismen // (Action-Mapping in web.xml *.cnc auf zentrales Servlet, // Wiederaufnehmen des Flusses aus URL-Encoding oder Hidden-Field bzw. Session) // beim nächsten Browser-Request beim nachfolgenden Befehl // wieder aufgenommen werden label <label_bezeichner>; // ein anspringbares Label zur Realisierung von Navigationslinks, nur in der main-procedure erlaubt local session:<varname>; // nur in der aktuellen procedure/function und in von dieser aufgerufenen procedures/functions gültige Variable logon { <body> } // Bereich, in dem keine Prüfung auf Berechtigung erfolgt, damit ein Einlogggen überhaupt möglich ist, nur in der main-procedure erlaubt procedure <procedure_name> ( <parameter> ) { <body> } // Procedure-Deklaration reset ( <String-Expression mit variablen_name> ); // Löschen einer Variable (session:xxx oder application:xxx), die Klammern sind zwingend erforderlich return; // Rückkehr aus Procedure return ( <return_expression> ); // Rückkehr aus Function while ( <bedingung, boolean-Expression> ) { <body> } // Schleife wird durchlaufen solange Bedingung == true, die geschwungenen Klammern sind zwingend erfoderlich Kommentare ---------- Wie in Java sind Inline-Kommentare mit doppeltem Schrägstrich ....; // Kommentar oder Bracketkommentare /* Kommentar, auch mehrzeilig */ möglich. Deklaration procedure --------------------- Die Deklaration einer procedure schließt ein Unterprogramm ohne Rückgabewert oder das Hauptprogramm main ein. In der Steuerdatei flow.cnc muss mindestens das Hauptprogramm main deklariert sein. procedure main () { ... } // end procedure main Bei Verwendung von Prozeduren (ausser main) muss die flowleading-Methode auf session stehen, sonst gibt es einen Runtime-Error. Dies hat seinen Grund darin, dass nicht der gesamte Stack, dieser kann sehr gross werden, zum Browser und von dort wieder zum Server gesendet werden soll. Lokale Variablen werden mit local (siehe dort) festgelegt. Ein Unterprogramm kann mit return; oder goto sprungziel; beendet werden. Achtung, beim Verlassen über goto werden lokale Variable und Referenz-Parameter nicht zurückgeschrieben. Der Stack der Applikation wird verworfen. Ausserdem kehrt der Steuerfluss beim Erreichen des Prozedur-Endes, das heisst der schliessenden geschwungenen Klammer ... } // end procedure zur aufrufenden Prozedur/Function zurück. Beim Aufruf über call können Parameter übergeben werden. call procName ( session:FORM_KEY ) Es sind beliebig viele Parameter erlaubt. Über das Attribute refParam kann die Variable per Referenz übergeben werden. Dabei werden die Parameter per value (Übergabe des Wertes ohne Rückwirkungen auf die aufrufende Procedure/Function) übergeben. Alternativ können die Parameter auch per reference (Zurückkopieren der in der aufgerufenen Procedure/Function aufgetretenen Änderungen in die aufrufende Procedure/Function) call procName ( refparam session:FORM_KEY ) Funktionsweise: Beim Start der procedure wird eine lokale Variable mit dem param-Namen aus dem procedure-Statement gebildet und der Wert aus dem call-Statement auf diese lokale Variable kopiert. Wenn der Parameter per Referenz (Schlüselwort refparam) übergeben wurde, wird beim Beenden der Procedure das Objekt vom inneren Variablen-Key (param-Name in der procedure-eklaration) zum äusseren Variablen-Key (param-Name im call- Statement) zurückkopiert. Deklaration function -------------------- Die Deklararation function schließt ein Unterprogramm mit einem Rückgabewert ein. function artikelLookUp () { ... } // end function artikelLookUp Bei Verwendung von Funktionen muss die flowleading-Methode auf session stehen, sonst gibt es einen Runtime-Error. Dies hat seinen Grund darin, dass nicht der gesamte Stack, dieser kann sehr gross werden, zum Browser und von dort wieder zum Server gesendet werden soll. Lokale Variablen werden mit local (siehe dort) festgelegt. Eine Function kann mit return ( <return_expression> ); oder goto sprungziel; beendet werden. Achtung, beim Verlassen über goto werden lokale Variable und Referenz-Parameter nicht zurückgeschrieben. Ausserdem kehrt der Steuerfluss beim Erreichen des Prozedur-Endes ... } // end function zur aufrufenden Prozedur/Function zurück. Der Rückgabewert der Function kann einer Variable zugewiesen werden: session:retVal := call funcName () Andererseits kann der Rückgabewert aber auch verworfen werden: call funcName() Die Verwendung eines Function-Call in einem Ausdruck ist nicht möglich, da die Expression-Engine getrennt von der Flow-Engine arbeitet und die Flow-Engine im Gegensatz zur Expression-Engine das Unterbrechen und Wiederaufnehmen des Flusses beim jsp-Befehl realisiert. Beim Aufruf über call können Parameter übergeben werden. session:retVal := call funcName ( session:FORM_KEY ) Es sind beliebig viele Parameter erlaubt. Über das Attribute refParam kann die Variable per Referenz übergeben werden. Dabei werden die Parameter per value (Übergabe des Wertes ohne Rückwirkungen auf die aufrufende Procedure/Function) übergeben. Alternativ können die Parameter auch per reference (Zurückkopieren der in der aufgerufenen Procedure/Function aufgetretenen Änderungen in die aufrufende Procedure/Function) session:retVal := call funcName ( refparam session:FORM_KEY ) Funktionsweise: Beim Start der procedure wird eine lokale Variable mit dem param-Namen aus dem procedure-Statement gebildet und der Wert aus dem call-Statement auf diese lokale Variable kopiert. Wenn der Parameter per Referenz (Schlüselwort refparam) übergeben wurde, wird beim Beenden der Procedure das Objekt vom inneren Variablen-Key (param-Name in der procedure-Deklaration) zum äusseren Variablen-Key (param-Name im call- Statement) zurückkopiert. Befehl call ----------- Der Befehl call ruft eine Prozedur oder Function auf. call procedure_name ( [parameter] ) Bei Funktionen kann der Rückgabe-Wert einer Variablen zugewiesen werden. session:retval := call procedure_name ( [parameter] ) Es ist aber auch möglich, den Rückgabe-Wert verfallen zu lassen. Der Aufruf einer CnC-Funktion in einer Expression (Ausdruck) ist nicht möglich, da die Flow-Engine zwar die Expression-Engine, aber die Expression-Engine nicht die Flow-Engine aufrufen kann. Das ist die Konsequenz aus der Unterbrechbarkeit der Flow-Engine. Im Stack des CnC-Controllers wird die Adresse in der aufrufenden Prozedur für den return vermerkt. Es ist möglich der gerufenen Prozedur Parameter mitzugeben. Dabei gibt es value- Parameter und reference-Parameter. Referenz-Parameter werden durch das vorgesetzte reservierte Wort 'refparam' in der procedure- bzw. function-Deklaration gekennzeichnet. Im call-Statement ist nicht erkennbar, ob es um einen Value- oder einen Referenz-Parameter handelt. Ich überlege, ob ich den Namen der aufzurufenden Prozedur/Funktion als String- Expression statt als Bezeichner übergebe. So können Functionpointer nachgebildet werden, aber die Compiler-Prüfung geht verloren. Befehl return ------------- Der Befehl return bricht die Abarbeitung der aktuellen Prozedur/Funktion ab und kehrt zur aufrufenden Prozedur/Funktion zurück. Falls im Stack des CnC-Status keine aufrufende Prozedur/Function gefunden werden kann, wird wieder mit dem Start der procedure main begonnen. return; // aus Prozedur Bei der Rückkehr aus einer Function ist die Rückgabe eines Wertes zwingend erfoderlich. return ( <return_expression> ); // aus Function Falls es keinen Rückgabewert aus einer Funktion gibt, muss return(null); geschrieben werden. Befehl goto ----------- Mit dem Befehl goto kann eine Sprungmarke (label) in der main-Prozedur oder ein Unterprogramm angesprungen werden. Die Möglichkeit Unterprogramme per goto anzuspringen, dient der Realisierung globaler Navigationslinks. Beim Aufruf eines goto wird der vorhandene CnC-Stack verworfen. Sprungmarken (Label) sind nur in der procedure main erlaubt. goto <label_name>; goto <procedure_function_name>; Deklaration label ----------------- Setzen einer Marke zum Anspringen durch goto. label <label_name>; Label sind nur in der main-Prozedur erlaubt, weil sie dediziert zum Realisieren von Navigationslinks dienen. Deklaration while ----------------- Die Deklaration while umschliesst eine Schleife, bei der vor jedem Durchlauf die Bedingung zur Ausführung geprüft wird. while ( <bedingungs_expression> ) { ... } // end while zum Beispiel while ( true ) // Endlos-Schleife { ... } // end while Die geschwungenen Klammern für den Body sind im Gegensatz zu Java zwingend erfoderlich. Deklaration do -------------- Der Befehl do umschliesst eine Schleife, bei der vor jedem, ausser dem ersten, Durchlauf die Bedingung zur Ausführung geprüft wird. Ein Durchlauf erfolgt also immer. do ( <bedingungs_expression> ) { ... } // end do oder do ( true ) // Endlos-Schleife { ... } // end do Die geschwungenen Klammern für den Body sind im Gegensatz zu Java zwingend erfoderlich. Deklaration for --------------- Ein for gibt es in CnC nicht, weil ich in einer Fluss-Steuerung keine Anwendung dafür sehe. Falls es jemand wünscht, kann ich es aber noch implementieren. Befehl break ------------ Der Befehl break bricht die aktuelle while- oder do-Schleife ab. break; Befehl continue --------------- Der Befehl continue springt zum Anfang der aktuellen while- oder do-Schleife. continue ; Deklaration if, elseif und else ------------------------------- Über die if-Deklaration kann die bedingte Ausführung von Anweisungen gesteuert werden. if ( <boolean_expression> ) { ... } // end if //else if ist beliebig oft möglich else if ( <boolean_expression> ) { ... } // end else if else { ... } // end else Die geschwungenen Klammern für den Body sind im Gegensatz zu Java zwingend erfoderlich. Befehl action ------------- Der Befehl action ruft eine Action-Methode auf. Action-Methoden repräsentieren den Controller in der MVC-Architektur. Sie werden vom zentralen Servlet de.cnc.CncServlet unter Mithilfe des ActionMethodClassCache aufgerufen. Klassen- und Methoden-Name der Action wird als String-Expression übergeben, wodurch er zur Laufzeit variabel sein kann. action ( <name_der_action_als_string> ) ; Action-Methoden sind static-Methoden in den jeweiligen Action-Klassen mit einer festgelegten Parameter-Liste. Der Package-Prefix der Action-Klassen wird durch die Methode getActionPackagePrefix() und getDefaultActionClassName(), die von der projekt- spezifischen Ableitung des CncServlet (z.B. CncDemoServlet), implementiert werden. Die Notation einer Action-Methode lautet "ActionClass#actionMethod" oder "actionMethod" bei CncDefaultActions#method oder der eigenen Default-Action-Klasse der Applikation (siehe Methode getDefaultActionClassName() des Applikations-Servlets. Beispiele sind de.cncdemo.actions.Bestellung und de.cncdemo.actions.CncDemoDefaultActions, wobei letztere Klase Action-Methoden enthält, deren Bezeichnungen keinen Prefix (Default) haben. Der Rückgabe-Wert der Action-Methoden kann für die weitere Verarbeitung ausgewertet werden. In Zukunft baue ich noch die optionale Übergabe von Parametern über ein Object- Array an die Action-Methoden in das Framework ein. Befehl jsp ---------- Der Befehl jsp zeigt eine JSP an. Hier bleibt der Fluss des CnC-Systems stehen und wird nach dem nächsten Browser-Request wieder aufgenommen. Name und Pfad der JSP wird als String-Expression übergeben, wodurch er zur Laufzeit variabel sein kann. jsp ( "pfad und dateiname.jsp als String" ); Die Pfadangabe muß relativ auf das Verzeichnis web (bei Deploment über ant) oder auf das Verzeichnis der Webapplikation im Tomcat (tomcat.home/webapps/appname) bezogen erfolgen. JSP´s stellen den View in der MVC-Architektur dar. Befehl reset ------------ Löschen eines Wertes von einem bestimmten SessionKey. Auf dem SessionKey kann ein Objekt beliebiger Klasse liegen. reset "sessionKey-String"; Der Befehl reset ist wie der entfallene Befehl set ein Relikt aus der Zeit der XML-Notation des CnC-Flusses. Er kann durch session:resetVar := null; ersetzt werden. Ohne Angabe des SessionKey werden alle Session-Variablen gelöscht. reset ( '' ); // löscht alle Session-Variablen Befehl invalidate ----------------- Aufruf session:invalidate(), wodurch die aktuelle Session zerstört und der User aus der Applikation geworfen wird. invalidate; Nach Abarbeitung von invalidate kann auf der aktuellen Session nicht mehr gearbeitet werden. Auch das Single-Step-Debug bricht ab. Deklaration logon ----------------- Damit das Logon möglich ist, kann für einen Befehlsabschnitt die User- Validierung ausgeschaltet werden. Dieser Bereich ist nur in der procedure main gestattet. Für alle Befehle im Flow-Script ausserhalb des logon-Blockes wird eine User-Validierung durchgeführt. logon { ... // nicht geprüfter Bereich } // logon Deklaration local ----------------- Mit dem Befehl localvar werden lokale Variable definiert. local sessionKey="..."/> Die Deklaration local darf nur am Beginn einer Prozedur/Funktion stehen. Bei Verwendung von local muss die flowleading-Methode auf session stehen, sonst gibt es einen Runtime-Error. Dies hat seinen Grund darin, dass nicht der gesamte Stack, dieser kann sehr gross werden, zum Browser und von dort wieder zum Server gesendet werden soll. Beim Auftreten von local wird das Objekt vom entsprechenden Session-Key (name="...") im FlowStack gesichert. Beim Beenden der procedure oder beim return-Befehl wird das vorherige Objekt zurückgeschrieben (nur Referenzkopie, kein clone). Wird der Fluss durch GOTO-Actions oder Fehler verlassen, unterbelibt das zurückschreiben, der aktuelle Stack verfällt. Bedingungen ----------- Bedingungen können in der if-, elseif-, while- und do-Deklaration verwendet werden. Sie werden durch boolsche Ausdrücke der Expression-Engine realisiert. if ( cnc_button == "save ) // Abfragen des Namens des betätigten Buttons if ( cnc_button_index >= 0 ) // Abfrage des Index des Buttons in Tabellen (in einfachen Forms -1) if ( cnc_link == "Anmeldeformular" ) // Abfrage action="..." der HTML-FORM oder Link HREF="..." // Wenn die aufgerufene Action (Dabei wird der Postfix des URL-Pattern *.cnc abgeschnitten) gleich // dem übergeben String ist, wird der entsprechende Befehl ausgeführt. if ( session:var == null ) // Abfrage Session-Variable auf nicht Existenz/null if ( request.param.userId != null ) // Abfrage Request-Parameter auf Existenz/nicht null Bedingung Link indiziert noch nicht implementiert Debugging --------- Zum Debugging stehen folgende Möglichkeiten zur Verfügung: 1. Ausgabe Status über Tag <cnc:debug/> in der JSP-Seite 2. Einzelschritt-Debug über singlestepdebug.jsp Einschalten im Script über session:CNC_SINGLE_STEP_DEBUG := "ON"; 3. Logging ins Tomcat-Startfenster bei Log-Level DEBUG 4. Ausgabe der Steuertabelle (Low-Level-Anweisungen) auf Datei zum Debugging Sehen Sie bitte hierzu die auskommentierte Zeile in CncServlet#init. //StringUtil.str2file( "" + FlowControl.getFlowControlTable() , "C:\\cnc\\debug\\flow.out" ) ; Reservierte Bezeichner ---------------------- CnC arbeitet extensiv mit reservierten Session- und Request-Keys um seine Funktionalität zu realisieren. Diese dürfen von der Applikation nicht benutzt werden. In den Klassen de.cnc.SessionKeys und de.cnc.RequestKeys sind entsprechende Konstanten festgelegt. Prinzipiell sollten Sie Namen die mit 'cnc' oder 'CNC beginnen sowie 'cnc' oder 'CNC' enthalten vermeiden. Unterdrücken des Caching im Browser ----------------------------------- In der Betriebsart Session-Leading ist es wichtig, das Caching der HTML-Seiten im Browser zu verhindern, weil die Applikation sonst verwirrendes Verhalten zeigt. Üblicherweise muss auch auch noch der Cache eines eventuell vorhandenen Proxys unterdrückt werden. Dazu muss folgender Code in allen JSPs eingebaut werden: <meta http-equiv="expires" content="Thu, 26 Dec 2000 00:00:00 GMT"> <meta http-equiv="pragma" content="no-cache"> <% response.addHeader( "Cache-Control" , "no-cache, must-revalidate" ) ; // unterdrücken Seiten-Caching %> oder response.addHeader("Cache-Control", "no-cache"); response.addHeader("Expires", "Thu, 26 Dec 2000 00:00:00 GMT"); Oder aufwändiger: SimpleDateFormat f = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss"); f.setTimeZone(TimeZone.getTimeZone("GMT")); String lastModified = f.format(new java.util.Date()) + " GMT"; response.setHeader("Last-Modified", lastModified); response.setHeader("Expires","Thu, 26 Dec 2000 00:00:00 GMT"); response.setHeader("Cache-Control","no-cache, must-revalidate"); response.setHeader("Pragma","no-cache"); Dafür gibt es das Tag <cnc:nocache> Das zentrale Servlet de.cnc.CncServlet enthält bereits entsprechenden Code. Weitere Servlets existieren in CnC-Applikationen nicht. Arbeit mit Frames ----------------- Wenn mehrere Frames verwendet werden, geht die Synchronisation beim Flow-Control-Mode Session-Leading verlorden. Das liegt daran, dass aus den verschiedenen Frames zu unterschiedlichen Zeitpunkten Requests an den Server abgesendet werden können. Der Flow-Control-Mode Session-Leading kontrolliert mit einer sich laufend ändernden Nummer (Synchronisations-Token), ob nicht der Back-Button benutzt wurde oder ein neues Browserfenster geöffnet wurde. Eine Alternative wäre die Benutzung des Flow-Control-Mode Browser-Leading, welcher aber keine Unterprogramme (ausschliesslich procedure main) erlaubt. Einen Ausweg ist die Benutzung der Optionen 'target' und 'cncStatusNoCheck="true"' des cnc:hrefgoto-Tags. In der Datei 'web.xml' muss der Schalter 'synchronized' fuer die Synchronisation der doRequest-Methode des CnCServlet auf 'true' gesetzt werden, damit es nicht zu Wettlaufproblemen bei den Request's in den unterschiedlichen Frames kommt. Ohne Frames sollte 'synchronized' aus Performancegruenden 'false' gesetzt werden. Die Applikation muss so gestaltet werden, dass in jedem Frame eine eigene Prozedur, welche über das cnc:hrefgoto-Tag angesteuert wird, gestartet wird. Es sollten keine JSP-Seiten direkt in den einzelnen Frames angesteuert werden, weil sich dann eventuell die Wurzel der Web- Applikation (im CnC-Demo-Beispiel von http://localhost:8080/cncdemo auf http://localhost:8080/cncdemo/frames) verschiebt und der Fluss- Steuerung die Kontrolle entzogen wird. Als erstes benötigen wir eine Seite mit einem Frameset <html lang="de"> <head> <title>CnC Demo Arbeit mit Frames main_frame.jsp</title> <link rel="stylesheet" type="text/css" href="cnc.css"> </head> <frameset cols="30%,70%"> <frame src="cnc_goto_frame_menu.cnc?CNC_STATUS=cncStatusNoCheck&CNC_SRC_JSP=/frame_main.jsp" name="LeftFrame"> <frame src="cnc_goto_frame_empty.cnc?CNC_STATUS=cncStatusNoCheck&CNC_SRC_JSP=/frame_main.jsp" name="RightFrame"> <noframes> Ihr Browser kann diese Seite leider nicht anzeigen! <cnc:hrefgoto href="begin" txt="Haupt-Menü"/> </noframes> </frameset> </html> Noch zu tun: eigene User-definierte-Tags für <frame src="... Vom Hauptframe wird über cnc_goto_ an Prozeduren (zur Erinnerung: über CnC-Gotos können Labels in der procedure main oder Prozeduren angesprungen werden) Dabei wird über den Parameter CNC_STATUS=cncStatusNoCheck die Prüfung des CnC-Status ausgeschaltet. In der Fluss-Steuerdatei flow.cnc werden die jeweiligen Prozeduren //*********************************** procedure frame_menu() { jsp( "/frames/frame_menu.jsp" ); } //*********************************** procedure frame_empty() { jsp( "empty.jsp" ); } //*********************************** Wenn zum Beispiel der linke Frame als Menü-Frame dient, muss die Weiterleitung in den rechten Frame mit CNC_STATUS=cncStatusNoCheck erfolgen: <cnc:hrefgoto href="frame_table_kunden" -- eine flow.cnc-Prozedur target="RightFrame" -- Name des Zielframes cncStatusNoCheck="true" -- CnC-Status-Check aus txt="Kunden-Liste"/> -- Link-Text Denkbare Erweiterungen ---------------------- Denkbar wäre eine Möglichkeit eigene Befehle ähnlich wie Custom- Tags in die Script-Sprache einzubringen. Solche Befhle müssten aus einem Java-Code-Teil, der ein bestimmtes Interface implementiert, und aus einer Deklaration der Syntax und des Verhaltens über eine Description-Datei in XML oder über Assertions bestehen. Zur Abbildung von Web-Apps mit Frames könnte man eine Art Multithreading einbauen. Die vorhandene Infrastruktur der Fluss-Steuerung eignet sich herausgelöst als Fluss-Steuerung (Workflow-Engine) für GUI- Applikationen (Ersatz von Status-Schaltern oder Finite-State- Machines) oder für J2EE-Applikationen.
Achtung: Erweiterungen und Fixes stelle ich ohne Historie
und ohne Ankündigung hier bereit. Lizenzbedingungen:
Die Programme, Quelltexte und Dokumentationen können ohne
irgendwelche Bedingungen kostenlos verwendet werden. |