Starke Verbesserungen in Model-Glue 3

Die Final-Version 3 des OpenSource-MVC-Frameworks Model-Glue für ColdFusion ist erschienen. Bereits mit der Beta-Version hatte ich keine Probleme festgestellt, konnte die 2er-Version ohne Anpassungen ersetzen und habe dabei zahlreiche neue Funktionen schätzen gelernt. Die wichtigsten hier zusammengefasst.

Es ist ja grundsätzlich schon einmal nicht selbstverständlich, dass man eine ältere Version eines Frameworks einfach so durch einen neuen Release ersetzen kann – ohne Anpassungen der Applikation. In der Regel deutet das nicht gerade auf grossartige Neuerungen hin sondern auf einen Bugfix-Release. Die MG3-Version liess zwar lange auf sich warten, bietet nun aber zahlreiche gute Gründe für ein Upgrade.

Helpers einfach aufrufen

Eine grossartige Erleichterung für mich ist die neue Möglichkeit, wie Hilfsfunktionen integriert werden können. Die sogenannten Helpers können als CFM-Dateien oder Components in einem speziellen Verzeichnis abgelegt werden, das wiederum im ColdSpring.xml definiert ist.

<property name="helperMappings"><value>/helpers</value></property>

ModelGlue durchforstet nun dieses Verzeichnis und stellt alle Hilfsbibliotheken (UDF) in den helpers-Scope. In meinen Applikationen benutzte ich häufig verschiedene Hilfsbibliotheken, um ein wenig den Überblick zu wahren. So kommt meistens eine Bibliothek fürs Datei-Handling zum Einsatz: file.cfc. Eine häufig verwendete Funktion dabei ist FileSize(). Um diese Funktion aufzurufen kann man nun schlicht folgenden Code verwenden:

<cfoutput>#helpers.file.FileSize(filename="test.doc")#</cfoutout>

Im MG2-Applikationen musste ich diese Funktion immer mühsam manuell aufrufen, entweder mit cfinvoke oder einem CreateObject(). Beides hatte aber den Nachteil, dass die Bibliotheken nicht einfach ohne weiteres verschoben werden konnten, und das Caching musste ebenfalls manuell gelöst werden. Alternativ habe ich die Hilfsbibliotheken schliesslich in der SimpleConfig von ModelGlue abgelegt, damit ich den einzelnen Beans jederzeit Zugriff auf die Hilfsfunktionen gewähren konnte. Das sah denn jeweils so aus im ColdSpring.xml:

<bean id="AppConfiguration" class="ModelGlue.Bean.CommonBeans.SimpleConfig">
<property name="Config">
    <map>
        <entry key="udfFile">
            <ref bean="udfFile" />
        </entry>
        <entry key="udfMail">
            <ref bean="udfMail" />
        </entry>
    </map>
</property>
</bean>

<bean id="userService" class="model.userService">
    <constructor-arg name="AppConfiguration">
        <ref bean="AppConfiguration" />
    </constructor-arg>
</bean>

<bean id="udfFile" class="udf.file" />
<bean id="udfMail" class="udf.mail" />

Den ganzen Plunder kann ich mir nun sparen, MG sei Dank.

getModelGlue().getBean() nicht mehr nötig

Components, die durch ColdSpring verwaltet worden sich, konnten im Controller jeweils mit getModelGlue().getBean(«myComponent»).doIt() aufgerufen und verwendet werden. Neu sind diese Objekte im beans-Scope zu finden, also zu Beispiel beans.myComponent.doIt(). Das geht definitiv einfacher von der Hand und passt natürlich zum Aufruf der helpers. Im Gegensatz zur einfachen Integration der helpers, müssen beans im cfcomponent-Tag über das beans-Attribut definiert werden:

<cfcomponent displayname="security" extends="ModelGlue.gesture.controller.Controller" beans="appConfiguration,userService" output="false">
<!--- hier kommen die Controller-Funktionen --->
</cfcomponent>

Wie man anhand des Beispiels sieht, werden mehrere Beans kommasepariert übergeben.

Nützliche Event-Typen

Ganz nützlich finde ich die Event-Typen. So können Events neu einem speziellen Event-Typ zugewiesen werden (Update dieses Beitrags unter Mehrere Event-Types in Model-Glue 3 für einen Event). Zum Beispiel beim Sicherheitsaspekten:

<event-handler name="admin.home" type="protected">
    <broadcasts>
        <message name="adminoverview" />
    </broadcasts>
    <views>
        <include name="adminhome" value="admin_home.cfm" />
    </views>
</event-handler>

Wie man hier sieht, findet keinerlei Überprüfung des Users statt, obwohl dies sicherlich notwendig wäre in einem Admin-Bereich. Die geschieht über das neue Type-Attribut, das hier auf protected gesetzt worden ist. Damit wir ein Event-Type aufgerufen, der wie folgt definiert werden könnte:

<event-type name="protected">
    <before>
        <broadcasts>
            <message name="LoginRequired" />
        </broadcasts>
        <results>
            <result name="NotLoggedIn" do="user.login" />
        </results>
    </before>
    <after>
        <!-- wird am Schluss des eigentlichen Events ausgefuehrt -->
    </after>
</event-type>

Nun wird jedesmal, wenn der Event «admin.home» aufgerufen wird, zuerst der event-type protected durchgeführt. Bisher musste man dafür die Funktion OnRequestStart des Frameworks bemühen, konnte dadurch aber nur mühsam verschiedene OnRequestStart-Szenarien abhandeln. Alternativ hätte man auch jedem Event einen entsprechenden Broadcast mitgeben können, was man aus nahe liegenden Gründen nicht getan hat.

Verschiedene Ausgabe-Formate

Ein brauchbares Feature, um das ich bereits früher froh gewesen wäre, ist das Format-Attribut für Broadcasts, Results und Views. Oftmals wird eine Applikation mit unterschiedlichen Gerätetypen aufgerufen, sprich nicht nur über einen Webbrowser, der HTML-Content verarbeitet, sondern auch mit Mobilephones, Air-Clients oder Ajax-Calls. Dabei werden oft die gleichen Daten benötigt, allerdings in einem anderen Format. Beispielsweise braucht man mit allen Geräten oder Clients eine Liste mit Artikel. Der Event mit ist also jedes Mal der selbe. Ein Beispiel:

<event-handler name="artikel">
    <broadcasts>
        <message name="artikel.list" />
    </broadcasts>
    <results>
    </results>
    <views format="html">
        <include name="body" template="dspArtikel.cfm" />
    </views>
    <views format="mobile">
        <include name="body" template="dspArtikel_mobile.cfm" />
    </views>
    <views format="air">
        <include name="body" template="airArtikel.cfm" />
    </views>
    <views format="ajax">
        <include name="body" template="jsonArtikel.cfm" />
    </views>
</event-handler>

In diesem Fall ist das Auslesen der Daten bei alle Fällen identisch, das müsste aber auch nicht sein. Die Format-Typen sind übrigens nicht normiert oder irgendwie im Framework hinterlegt, sondern werden grundsätzlich über den Url-Parameter requestFormat gesetzt. Der Wert kann selbstverständlich auch manuell in der Event-Struktur angepasst werden, beispielsweise in einer onRequestStart()-Funktion zur Unterscheiden von klassischen und Mobile-Browsern – sehr flexibel, ganz nach meinem Gusto. So, das wären meine Lieblings-Goodies von Model-Glue 3 gewesen. Weitere Neuigkeiten und Tipps & Tricks sind in den MG-Docs zu finden.

Verwandte Blog-Einträge

Kommentare

Leave this field empty
Ihren Kommentar hinzufügen

Falls Sie abonnieren, werden alle neuen Kommentare zu diesem Thema an Ihre E-Mail-Adresse gesandt.

TrackBacks

Es gibt keine Trackbacks für diesen Eintrag.

Trackback URL dieses Eintrages:
http://www.samelis.ch/blog/mischa/trackback.cfm?id=1CC19AEA-3C1A-4DA7-92F3C5F1A9661EA6