Einführung in die OfBiz Entwicklung

$Id: vom RCS vergebene eindeutige ID $

$Date: Vom RCS vergebenes Datum

Zusammenfassung

Dies ist die Übersetzung der Einführung in die Entwicklung mit Apache Open for Business (OfBiz) mit persönlichen Ergänzungen. (https://cwiki.apache.org/OFBIZ/ofbiz-tutorial-a-beginners-development-guide.html)

Als Basis dient OFBiz in Version 11.04. Die Beispiel sollten aber auch mit der Version 10.04 (wahrscheinlich auch mit 12.04) funktionieren.


Inhaltsverzeichnis

I. Grundlagen
1. Überblick
Grundlegende Hinweise
Komponente anlegen
Erklärungen zu ofbiz-component.xml
Anlegen der web app
2. Einführung User Interface
Fortgeschrittenes am User Interface
Fehler und Ursachen
Inhalt der Person Entität als Formular anzeigen
Fehler und Ursachen
3. Anwendung in der Anwendungsleiste anzeigen
UI Beschriftungen anlegen
4. Anwendung absichern
Anwendung durch Authentifizierung absichern
5. Hallo Welt!
Die erste praktische Anwendung (Hallo Welt...)

Teil I. Grundlagen

Kapitel 1. Überblick

  • Anlegen und laden der eigenen Komponente

  • Anlegen einer fortgeschrittenen GUI Komponente, inkl. Datenbank und absichern der Anwendung

  • Weitere Datenbank Interaktionen (CRUD) und Valdierung von Feldparametern

  • Aufrufen von automatischen Diensten, mehrere Dienste als Gruppe aufrufen, Interfaces anlegen und Parameterübergaben zwischen Diensten

  • Eigene Entitäten, Erweiterung der OOTB (Out-Of-The-Box) Entitäten und XML Dateien für eigene Anwendung anpassen

  • Kommunikation zwischen Client und Server mit AJAX

Grundlegende Hinweise

  • Für zusätzliche Hinweise lohnt sich ein Blick in die Beispielkomponenten. Die in jeder OFBiz Version mitgelieferten Beispielkomponenten passen zur jeweiligen Version. Jede neue Funktion wird in OFBiz zuerst in den Beispielkomponenten aufgeführt. Ein Blick in die Beispiele lohnt sich also immer.

  • Bevor Sie mit der Entwicklung einer Komponente beginnen sollten Sie unbedingt folgendes gelesen haben: OFBiz Contributors Best Practices , Coding Conventions und Best Practices Guide

  • Kopieren Sie keine Dateien von anderen Komponenten wenn die Revisionsnummer mitkopiert wird. Legen Sie besser, falls notwendig, eine neue Datei an und kopieren dann den entsprechenden Inhalt. Kümmern Sie sich auch um den vermeintlich toten Code.

  • Der beste Ausgangspunkt für (englischsprachige) Hilfe ist OFBiz Documentation Index .

  • Widmen Sie den Ausgaben auf der Konsole vom Anfang an ihre Aufmerksamkeit.

  • Den Quellcode zu den Anwedungen finden sie unter: Quellcode laden

Komponente anlegen

  1. Legen Sie im Verzeichnis hot-deploy ein neues Verzeichnis practice an. Der Name des Verzeichnisses sollte dem Namen der Anwendung entsprechen die entwickelt wird. Anmerkung: die Entwicklung findet ausschließlich in diesem Verzeichnis statt.

  2. Legen Sie die Datei ofbiz-component.xml im Verzeichnis ( hot-deploy/practice ) mit folgendem Inhalt an.

    <?xml version="1.0" encoding="UTF-8"?>
    <ofbiz-component name="practice"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/ofbiz-component.xsd">
          <resource-loader 	name="main" type="component"/>
        <webapp name="practice"
           title="Practice"
           server="default-server"
           base-permission="OFBTOOLS"
           location="webapp/practice"
           mount-point="/practice"
           app-bar-display="false"/>
    </ofbiz-component>
    
    						

Erklärungen zu ofbiz-component.xml

  1. Über die ofbiz-component.xml Datei wird OFBiz mitgeteilt wo die Ressourcen sind und welche Elemente zum Classpath hinzuzufügen sind.

  2. Der 'resource-loader name' kann jeder beliebiger String sein. In diesem Beispiel verwenden wir " main ". Der " type " veranlasst OFBiz die Komponente zu laden.

    <resource-loader name="main" type="component"/>
    								
    						

  3. Die Bedeutung der Attribute am webapp Tag sind wie folgt:

    <webapp name="practice"
           title="Practice"
           server="default-server"
           base-permission="OFBTOOLS"
           location="webapp/practice"
           mount-point="/practice"
           app-bar-display="false"/>
    
    						

    • name : legt den Namen der Web-Anwendung fest

    • title : Dies ist der Titel der Anwendung welcher in der Haupt-/Top-Navigation angezeigt wird.

    • server : Darüber wird OFBiz angezeigt, welcher Server zu verwenden ist.

    • base-permission : Dieser Wert zeigt an, dass der Nutzer die Berechtigung OFBTOOLS benötigt um die Anwedung nutzen zu können. Da der Nutzer "Admin" diese Berechtigung hat muss kein Nutzer angelegt werden.

    • location : Dies ist das Standardverzeichnis für den Server

    • mouont-point : Dies ist die URL welche für die Anwendung genutzt wird um auf die Anwendung zuzugreifen. In diesem Fall wird es http://localhost:8080/practice sein.

    • app-bar-display : Damit wird angezeigt ob die Anwendung in den Hauptanwendungsreitern ("main application tabs") erscheinen soll.

Anlegen der web app

  1. Legen Sie das Verzeichnis webapp im Verzeichnis der Komponente practice an ( hot-deploy/practice/webapp ). Dieses Verzeichnis enthält alle webapp spezifischen Dateien der neuen Anwendung.

  2. Legen Sie ein Unterverzeichnis practice im webapp Verzeichnis an, welches den gleichen Namen trägt wie das Verzeichnis für die neue Anwendung ( hot-deploy/practice/webapp/practice ). Eine Komponente kann mehrere Anwendungen haben. Z.B. hat die Komponente marketing die beiden webapps marketing und sfa . Die webapp, welche wir anlegen, wird weiterhin dem JEE Webapp Standard entsprechen.

  3. Legen Sie das WEB-INF Verzeichnis an ( hot-deploy/practice/webapp/practice/WEB-INF ).

    Eine OFBiz Web-Anwendung benötig zwei Konfigurationsdateien: controller.xml und web.xml

    Über die controller.xml wird gesteuert wie mit den Anfragen der Besucher zu verfahren ist, d.h. welche Aktionen empfangen werden und welche Seite zu rendern sind. web.xml teilt OFBiz mit welche Ressourcen der Web-Anwendung zur Verfügung stehen (Datenbanken und Geschäftlogik) und wie Web-bezogene Vorgänge zu behandeln sind. Beispiele dafür sind Willkommensseite, Seitenumleitungen und Fehlerseiten.

  4. Lege eine Datei mit dem Namen web.xml im Verzeichnis hot-deploy/practice/webapp/practice/WEB-INF/ (entspricht den JEE Spezifikationen) an. Der Inhalt der Datei kann von einer anderen Komponente kopiert werden (z.B. /framework/example). Die wichtigen Werte, die geändert werden müssen, sind <display-name> , localDispatcherName , mainDecoratorLocation und webSiteId .

    <context-param>
        <param-name>webSiteId</param-name>
        <param-value>PRACTICE</param-value>
        <description>A unique ID used to look up the WebSite entity to get information about catalogs, etc.</description>
    </context-param>
    <context-param>
         <param-name>localDispatcherName</param-name>
         <param-value>practice</param-value>
         <description>A unique name used to identify/recognize the local dispatcher for the Service Engine</description>
    </context-param>
    <context-param>
         <param-name>mainDecoratorLocation</param-name>
         <param-value>component://practice/widget/CommonScreens.xml</param-value>
         <description>The location of the main-decorator screen to use for this webapp; referred to as a context variable in screen def XML files.</description>
    </context-param>
    						

    • param-value für webSiteId sollte erstmal PRACTICE sein. Im späteren Verlauf werden wir darauf noch einmal genauer eingehen.

    • Der param-value für mainDecoratorLocation erstmal component://practice/widget/CommonScreens.xml sein. Detailiertere Erläuterungen dafür folgen ebenfalls später. Dieser Wert wird genutzt um auaf die main decorator location in Anzeigen zu verweisen: ${parameters.mainDecoratorLocation} .

      Damit machen wir den Code unabhängiger gegenüber Pfadänderungen. Falls der main decorator auf einem anderen Pfad verschoben wird, so muss dies nur an dieser Stelle geändert werden. Damit wird es auch leichter bestehenden Code in anderen Komponenten ohne Änderungen wiederzuverwenden.

  5. Legen Sie die Datei controller.xml an. Am Anfang wird diese Datei klein und einfach sein, aber mit den Anforderungen wachsen. Für's erst fügen Sie bitte folgendes ein:

    <?xml version="1.0" encoding="UTF-8"?>
    <site-conf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/site-conf.xsd">
           <include location="component://common/webcommon/WEB-INF/common-controller.xml"/>
           <description>Practice Component Site Configuration File</description>
           <owner>Copyright 2001-2009 The Apache Software Foundation</owner>
           <handler name="screen" type="view" class="org.ofbiz.widget.screen.ScreenWidgetViewHandler"/>
           <!-- Request Mappings -->
           <request-map uri="main">
               <security https="false" auth="false"/>
               <response name="success" type="view" value="main"/>
           </request-map>
           <!-- end of request mappings -->
           <!-- View Mappings -->
           <view-map name="main" type="screen" page="component://practice/widget/PracticeScreens.xml#main"/>
           <!-- end of view mappings -->
    </site-conf>
    
    						

  6. Das Gerüst für die Fehlerbehandlung

    1. Legen Sie ein neues Verzeichnis error in folgendem Pfad an: hot-deploy/practice/webapp/practice/ .

    2. Legen Sie eine Datei error.jsp im error Verzeichnis an. Der Inhalt der Datei kann für den Anfang wieder von einer jeden anderen existierenden Komponente kopiert werden, z.B. von einer example Komponente.

      Der Ort für die Fehlerseite wird am Anfang der controller.xml Datei festgelegt. (!! fehlt im Beispiel !!). Sie werde eine error.jsp Datei anlegen müssen um Fehlermeldungen an den Nutzer ausgeben zu können.

  7. Legen Sie das Verzeichnis widget im Verzeichnis hot-deploy/practice an. Dieses Verzeichnis wird Ihre Formulare, Menüs und Seiten enthalten welche für das UI verwendet werden.

  8. Legen Sie eine Datei mit dem Namen PracticeScreens.xml im Verzeichnis widget an. Der Inhalt der Datei kann wieder von einer anderen Komponente kopiert werden (z.B. Example ).

    <?xml version="1.0" encoding="UTF-8"?>
    <screens xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/widget-screen.xsd">
        <screen name="main">
            <section>
                <widgets>
                    <label text="This is first practice"/>
                </widgets>
            </section>
        </screen>
    </screens>
    
    						

    Damit sind Sie dann in der Lage Bildschirmansichten zu erzeugen. Sehr hilfreich dafür ist der Best Practices Guide .

  9. Jetzt sind alle grundlegenden Dinge an ihre Platz, egal wie groß oder komplex die Anwendung werden wird.

    Eine Anfrage über den Browser geht immer an eine spezifische Ressoruce. Nehmen wir zum Beispiel die Anfrage http://localhost:8080/practice/control/main (GET).

    1. Wenn OFBiz eine solche Anfrage erhält wird zuerst in /practice section nachgeschaut. Dies kommt daher, dass wir in der ofbiz-component.xml Datei den Mount-Punkt auf /practice gesetzt haben. Die Verarbeitung erfolgt also über unsere practice Komponente.

    2. Anschließend wird in der controller.xml nachgeschaut. Innerhalb der controller.xml haben wir request-maps und view-maps definiert. Wenn eine request-map mit dem Name main gefunden wird, dann wird die entsprechende view-map herangezogen.

      Eine request-map kann entweder einen View oder, wie wir später sehen werden, ein Event oder Dienst definieren. Falls ein View definiert wird, so wird in der controller.xml nach einem view-map Einrag geschaut welcher als value den Namen trägt welcher in request-map gesetzt wurde.

    3. Ab hier halten wir es einfach und nehmen an, dass alle Anfragen an den type=screen gehen. In diesem Fall spezifierziert der page Tag einen Pfad zur Datei für die Screen definition. Sowie eine Screen-Namen welcher nach dem # Zeichen angezeigt wird.

  10. Nun wird es Zeit unsere erste practice-OFBiz-Anwendung zu starten.

    Starten Sie den Server mit dem Kommando ./startofbiz.sh oder über java -Xmx256M -jar ofbiz.jar (-Xmx256M sorgt dafür, dass genügend Speicher zur Verfügung steht). Anschließend die URL http://localhost:8080/practice/control/main über den Browser aufrufen. Jetzt sollte der Browser folgende Seite zeigen.

  11. Legen Sie im WebApp-Verzeichnis die Datei index.jsp an ( practice/webapp/practice ). Der Inhalt kann wieder von einem der Beispiele kopiert werden. Diese Datei ist dafür verantwortlich die Anfragen auf http://localhost:8080/practice/ auf control/main umzuleiten. Eine Anfrage der Form http://localhost:8080/practice/unknown/request wird auf den redirectPath umgeleitet welcher in der web.xml definiert ist. In solch einem Fall wird der ContextFilter die Anfrage herausfiltern und auf die entsprechende Seite umleiten.

Kapitel 2. Einführung User Interface

Fortgeschrittenes am User Interface

  1. Nun wird es Zeit einen decorator für den screen der Anwendung anzulegen. Legen Sie die Datei CommonScreens.xml im Verzeichnis widget an. Diese Datei enthält die allgemeinen screens welche durchweg in der Anwendung verwendet werden. Ein allgemeiner screen könnte ein Kopf- und ein Fußteil haben. Jeder andere Screen welches diesen als decorator hat dann ebenfalls Kopf- und Fußteil.

    <?xml version="1.0" encoding="UTF-8"?>
    <screens xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/widget-screen.xsd">
        <screen name="main-decorator">
            <!-- The main-decorator screen 'wraps' or 'decorates' all of the screens in the
                practice component. It is also decorated - by the GlobalDecorator screen. -->
            <section>
                <actions>
                    <!-- base/top/most specific map first, then more common map added for shared labels.
                        Setting things up this way enables a component to redefine the more common
                        UI labels. -->
                    <property-map resource="CommonUiLabels" map-name="uiLabelMap" global="true"/>
                    <property-map resource="PracticeUiLabels" map-name="uiLabelMap" global="true"/>
                    <!-- The layoutSettings field is a Map that is used to pass variables and layout
                        information to the GlobalDecorator and any templates that it uses. -->
                    <set field="layoutSettings.companyName" from-field="uiLabelMap.PracticeCompanyName" global="true"/>
                    <set field="activeApp" value="practice" global="true"/>
                    <!-- Default (main) javascript files -->
                    <set field="layoutSettings.javaScripts[+0]" value="/images/prototypejs/validation.js" global="true"/>
                    <set field="layoutSettings.javaScripts[]" value="/images/prototypejs/prototype.js" global="true"/>
                    <set field="applicationMenuName" value="PracticeAppBar" global="true"/>
                    <set field="applicationMenuLocation" value="component://practice/widget/PracticeMenus.xml" global="true"/>
                </actions>
                <widgets>
                    <include-screen name="GlobalDecorator" location="component://common/widget/CommonScreens.xml"/>
                </widgets>
            </section>
        </screen>
        
        <screen name="CommonPracticeDecorator">
            <section>
                <widgets>
                    <decorator-screen name="main-decorator">
                        <decorator-section name="body">
                            <decorator-section-include name="body"/>
                        </decorator-section>
                    </decorator-screen>
                </widgets>
            </section>
        </screen>
    </screens>    
    

    Wie immer können Sie Bezug auf die CommonScreens.xml Datei aus dem Beispielen nehmen und Beispiele zur Verwendung von main-decorator einsehen. Zu diesem Thema finden Sie wichtige Informationen unter den beiden Links: Understanding the OFBiz Widget Toolkit und den Abschnitt "The Decorator" in den FAQ .

  2. Legen Sie ein Menü für die Anwendung an. Dafür legen Sie eine Datei Namens PracticeMenus.xml im Verzeichnis widget der Komponente an. Ziehen Sie in die Datei ExampleMenus.xml des Beispielprojektes als Referenz heran.

    <?xml version="1.0" encoding="UTF-8"?>
    <menus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/widget-menu.xsd">
        <menu name="PracticeAppBar" title="PracticeApplication" extends="CommonAppBarMenu" extends-resource="component://common/widget/CommonMenus.xml">
            <menu-item name="main" title="Main"><link target="main"/></menu-item>
        </menu>
    </menus>
    

    Binden Sie dieses Menüdatei in ihren CommonPracticeDecorator wie folgt ein.

    <screen name="CommonPracticeDecorator">
            <section>
                <widgets>
                    <include-menu location="component://practice/widget/PracticeMenus.xml" name="PracticeAppBar"/>
                    <decorator-section-include name="body"/>
                </widgets>
            </section>
        </screen>
    

  3. Legen Sie das Verzeichnis actions im Verzeichnis WEB-INF an. In dieses Verzeichnis werden wir Skripte ablegen. Über Skipte werden Daten zur Laufzeit bereitgestellt. Die Skripte sind Groovy-Skripte (in früheren Versionen wurden beanshell-Skripte verwendet). Unser Skript wird Daten aus der Datenbank lesen und zur Laufzeit für das UI aufbereiten.

    Referenzen: Tips & Tricks while working with Groovy und http://groovy.codehaus.org/ .

    Achten Sie bei Groovy-Skripten immer auf die verwendeten Imports. Importieren Sie immer nur das was auch Verwendung findet. Um Log-Meldungen zu schreiben verwenden Sie bitte von Anfang an die Debug -Klasse.

    Legen Sie eine Datei mit dem Namen person.groovy im Verzeichnis actions an. Dieses Skript wird alle Werte für die Entität Person aus der Datenbank lesen. Für den Moment ist der Code mit einer Zeile wirklich winzig.

    context.persons = delegator.findList("Person", null, null, null, null, false);
    

    Der obige Code zieht alle Werte von der Entität Person und legt sie in den Context der entsprechenden Person. In der ftl Datei wird über die Liste der Personen iteriert.

    Wichtige Informationen dazu finden Sie unter: Which variables are available in screen context?

  4. Im Verzeichnis practice/webapp/practice/ legen sie nun die Datei person.ftl an. Diese Datei ist für die Anzeige der Werte, welche über das Groovy-Skript gelesen wurden, verantwortlich.

    Siehe dazu auch: http://freemarker.sourceforge.net/docs/ .

    Im Moment brauchen Sie nur über die Liste der Personen aus dem Context zu iterieren. Dazu sind die wenigen folgenden Zeilen Code notwendig.

    <#if persons?has_content>
      <h2>Some of the people who visited our site are:</h2>
      <br>
      <ul>
        <#list persons as person>
          <li>${person.firstName?if_exists} ${person.lastName?if_exists}</li>
        </#list>
      </ul>
    </#if>

  5. Nun legen Sie einen screen mit dem Namen person über die Datei PracticeScreens.xml an. Gleichzeitig erzeugen Sie einen neuen Menüeintrag über die PracticeMenus.xml Datei.

    Der neue Menüeintrag in der PracticeScreens.xml sieht folgender Maßen aus:

    <screen name="person">
            <section>
                <actions>
                    <script location="component://practice/webapp/practice/WEB-INF/actions/person.groovy"/>
                </actions>
                <widgets>
                    <decorator-screen name="CommonPracticeDecorator" location="${parameters.mainDecoratorLocation}">
                        <decorator-section name="body">
                            <platform-specific>
                                <html>
                                    <html-template location="component://practice/webapp/practice/person.ftl"/>
                                </html>
                            </platform-specific>
                        </decorator-section>
                    </decorator-screen>       
                </widgets>
            </section>
        </screen>															

  6. Nun ändern Sie die controller.xml Datei so, dass auf den neuen screen verwiesen wird.

    <?xml version="1.0" encoding="UTF-8"?>
    <site-conf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/site-conf.xsd">
    
    	<include location="component://common/webcommon/WEB-INF/common-controller.xml" />
    	<description>Practice Component Site Configuration File</description>
    	<owner>Copyright 2001-2009 The Apache Software Foundation</owner>
    
    	<handler name="screen" type="view"
    		class="org.ofbiz.widget.screen.ScreenWidgetViewHandler" />
    
    	<!-- Request Mappings -->
    	<request-map uri="main">
    		<security https="false" auth="false" />
    		<response name="success" type="view" value="main" />
    	</request-map>
    	<request-map uri="person">
    		<security https="false" auth="true" />
    		<response name="success" type="view" value="person" />
    	</request-map>
    	<!-- end of request mappings -->
    
    	<!-- View Mappings -->
    	<view-map name="main" type="screen"
    		page="component://practice/widget/PracticeScreens.xml#main" />
    	<view-map name="person" type="screen"
    		page="component://practice/widget/PracticeScreens.xml#person" />
    	<!-- end of view mappings -->
    
    </site-conf>
    

    Nun starten Sie die Anwendung und prüfen das Ergebnis http://localhost:8080/practice/control/person .

    Das Beispiel kann ohne Anmeldung aufgerufen werden. Wegen besser Sichtbarkeit wurde für das Bildschirmfoto eine anderes Thema (Theme) gewählt. Dazu ist allerdings eine Anmeldung notwendig.

    Falls also ihr screen kein Menü enthält, aktivieren Sie die Authentifizierung. Sobald auth="false" in der controller.xml Datei auf auth="true" für die URI person gestellt wurde wird eine Anmeldung benötigt und dann erscheint auch das Menü.

Fehler und Ursachen

Es ist alles soweit erledigt, die ersten Anfragen an OFBiz werden gestartet und dann das: irgend etwas geht schief. Mögliche Fehler und ihre Ursachen für dies Abschnitt:

  • Der Aufruf http://localhost:8080/practice/control/person liefert folgende Fehlermeldung:

    Message: Unknown request [person]; this request does not exist or cannot be called directly.

    Lösung: Überprüfen Sie die Groß-/Kleinschreibung und Pfade zu den Dateien (besonders person.groovy, person.ftl und actions). Die originale, englische Anleitung ist an ein paar Stellen diesbezüglich Fehlerhaft.

    Dies betrifft auch die Groß-/Kleinschreibung in den Dateien: PracticeScreens.xml und controller.xml .

  • Der Aufruf http://localhost:8080/practice/control/person liefert folgende Fehlermeldung:

    org.ofbiz.widget.screen.ScreenRenderException: Error rendering screen [component://common/widget/CommonScreens.xml#login]: java.lang.IllegalArgumentException: Could not find screen with name [main-decorator] in class resource [component://practice/widget/CommonScreens.xml] (Could not find screen with name [main-decorator] in class resource [component://practice/widget/CommonScreens.xml])

    Lösung: Prüfen Sie den Aufbau der CommonScreens.xml Datei.

Inhalt der Person Entität als Formular anzeigen

  1. Fügen Sie einen weiteren Punkt zum Menü in der PracticeMenus.xml hinzu.

  2. Legen Sie ein Datei namens PracticeForms.xml im Verzeichnis widget an. Erzeugen Sie ein Formular für eine Liste um die Datensätze der Entität Person anzuzeigen. (Nehmen Sie Bezug ExampleScreens.xml und ExampleForms.xml )

    <?xml version="1.0" encoding="UTF-8"?>
    <forms xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/widget-form.xsd">
        <form name="ListPersons" type="list" list-name="persons" list-entry-name="person" target="updatePracticePerson">
            <auto-fields-service service-name="updatePracticePerson" default-field-type="edit" map-name="person"/>
            <field name="partyId"><hidden/></field>
            <field name="deleteLink" title="" widget-style="buttontext">
                <hyperlink target="deletePracticePerson" description="${uiLabelMap.CommonDelete}" also-hidden="false">
                    <parameter param-name="partyId" from-field="person.partyId"/>
                </hyperlink>
            </field>
            <field name="submitButton" title="${uiLabelMap.CommonUpdate}"><submit button-type="button"/></field>
        </form>
    </forms>
    
    						

  3. Erzeugen Sie in der CommonScreens.xml Datei einen weiteren screen mit den Namen personForm und fügen Sie folgendes Formular für Listen ein.

    <screen name="PersonForm">
            <section>
                <actions>
                    <set field="headerItem" value="personForm"/>
                    <set field="titleProperty" value="PageTitlePracticePersonForm"/>
                    <entity-condition entity-name="Person" list="persons"/>
                </actions>
                <widgets>
                    <decorator-screen name="CommonPracticeDecorator" location="${parameters.mainDecoratorLocation}">
                        <decorator-section name="body">
                            <label text="Person List" style="h2"/>
                            <include-form name="ListPersons" location="component://practice/widget/PracticeForms.xml"></include-form>
                        </decorator-section>
                    </decorator-screen>       
                </widgets>
            </section>
    </screen>
    
    						

  4. Jetzt muss noch controller.xml angepasst werden um den screen anzuzeigen.

    Fügen Sie dazu bitte folgende Abschnitte an die entsprechenden stellen der controller.xml Datei ein.

    <request-map uri="PersonForm">
        <security https="false" auth="true"/>
        <response name="success" type="view" value="PersonForm"/>
    </request-map>
    <request-map uri="updatePracticePerson">
        <security https="true" auth="true"/>
        <event type="service" invoke="updatePracticePerson"/>
        <response name="success" type="view" value="PersonForm"/>
        <response name="error" type="view" value="PersonForm"/>
    </request-map>
    

    und

        <view-map name="PersonForm" type="screen" page="component://practice/widget/PracticeScreens.xml#PersonForm"/>
    

    Im Unterschied zur Liste der Personen erfordert das Formular nun die Authentifizierung ( auth="true" ).

  5. Es muss die Datei PracticeScreens.xml angepasst werden. Ergänzen Sie die Datei an passender Stelle um folgende Zeilen.

    <screen name="PersonForm">
        <section>
            <actions>
                <set field="headerItem" value="personForm"/>
                <set field="titleProperty" value="PageTitlePracticePersonForm"/>
                <entity-condition entity-name="Person" list="persons"/>
            </actions>
    
            <widgets>
                <decorator-screen name="CommonPracticeDecorator" location="${parameters.mainDecoratorLocation}">
                    <decorator-section name="body">
                        <label text="Person List" style="h2"/>
                        <include-form name="ListPersons" location="component://practice/widget/PracticeForms.xml"/>
                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>
    

  6. Es muss noch ein Service definiert werden. Erzeugen Sie die Datei /practice/servicedef/services.xml an.

    <?xml version="1.0" encoding="UTF-8"?>
    
    <services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/services.xsd">
        <description>Practice Services</description>
        <!-- Party related Services -->
    
        <service name="updatePracticePerson" default-entity-name="Person"
            engine="simple"
            location="component://practice/script/org/hotwax/practice/PracticeServices.xml"
            invoke="updatePracticePerson" auth="true">
    
            <description>Update a person</description>
    
            <auto-attributes include="pk" mode="IN" optional="false" />
            <attribute name="firstName" mode="IN" type="String"
                optional="false" />
            <attribute name="middleName" mode="IN" type="String"
                optional="true" />
            <attribute name="lastName" mode="IN" type="String" optional="false" />
        </service>
    
    </services>
    

  7. Die Service-Definition muss in der ofbiz-component.xml eingebunden werden. Dazu fügen sie folgende Zeile an passender Stelle ein.

    <service-resource type="model" loader="main" location="servicedef/services.xml"/> 
    

  8. Nun starten Sie die Anwendung und rufen http://localhost:8080/practice/control/PersonForm auf. Nach der Anmeldung sehen sie folgendes:

Das erste Formular ist erstellt auch wenn noch nicht alle Funktionen implementiert sind. Wir werden dies im weiteren noch nachholen.

Kleine Rekapitulation, bis jetzt haben Sie an folgendem gearbeitet: controller requests mappings, Screen widget, form widget, Decorator, Menus, groovy, ftl.

Fehler und Ursachen

Mögliche Fehler und ihre Ursachen für dies Abschnitt:

  • Aufruf von alhost:8080/practice/control/PersonForm liefert folgendes:

    org.ofbiz.widget.screen.ScreenRenderException: Error rendering screen [component://common/widget/CommonScreens.xml#GlobalDecorator]: java.lang.RuntimeException: Error rendering included form named [ListPersons] at location [component://practice/widget/PracticeForms.xml]: java.lang.IllegalArgumentException: Error finding Service with name updatePracticePerson for auto-fields-service in a form widget (Error rendering included form named [ListPersons] at location [component://practice/widget/PracticeForms.xml]: java.lang.IllegalArgumentException: Error finding Service with name updatePracticePerson for auto-fields-service in a form widget)

    Lösung: Die Einträge für updatePracticePerson in der controller.xml könnten fehlerhaft sein. Oder die service definition ( servicedef/services.xml ) sind fehlerhaft oder nicht in der ofbiz-component.xml Datei eingebunden.

  1. Die Anwendung benötigt noch einen main Decorator über den die Auszeichnung erfolgt.

    Legen Sie einen screen mit dem Namen main-decorator in der CommonScreens.xml . (Nehmen Sie CommonScreens.xml aus dem Beispielen als Referenz.)

    <screen name="main-decorator">
            <section>
                <actions>
                    <property-map resource="CommonUiLabels" map-name="uiLabelMap" global="true"/>
                    <set field="layoutSettings.companyName" from-field="uiLabelMap.PracticeCompanyName" global="true"/>
                    <set field="activeApp" value="practice" global="true"/>
                    <set field="applicationMenuName" value="PracticeAppBar" global="true"/>
                    <set field="applicationMenuLocation" value="component://practice/widget/PracticeMenus.xml" global="true"/>
                </actions>
                <widgets>
                    <include-screen name="GlobalDecorator" location="component://common/widget/CommonScreens.xml"/>
                </widgets>
            </section>
    </screen>
    

  2. Den Decorator haben Sie bereits in den CommonPracticeDecorator screen ( PracticeScreens.xml ) eingefügt.

Kapitel 3. Anwendung in der Anwendungsleiste anzeigen

Inhaltsverzeichnis

UI Beschriftungen anlegen

Um die Anwendung in der Anwendungsleiste anzuzeigen muss die ofbiz-component.xml Datei angepasst werden. Dazu ändern Sie den Parameter app-bar-display auf true .

          <webapp name="practice" title="Practice" server="default-server"
        base-permission="OFBTOOLS" location="webapp/practice" mount-point="/practice"
        app-bar-display="true" />

Wenn Sie die Anwendung jetzt starten und werden Sie die Practice -Anwendung in der Anwendungsleiste finden.

UI Beschriftungen anlegen

  1. Legen Sie das Verzeichnis config im Verzeichnis der Komponente an /practice/ .

    Wichtig: Vergessen Sie nicht den Eintrag für den Classloader

    <classpath type="dir" location="config" />
    

    in der ofbiz-component.xml Datei.

    <?xml version="1.0" encoding="UTF-8"?>
    <ofbiz-component name="practice"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/ofbiz-component.xsd">
    
        <resource-loader name="main" type="component" />
    
        <classpath type="dir" location="config"/>
    
        <service-resource type="model" loader="main" location="servicedef/services.xml"/> 
    
        <webapp name="practice" title="Practice" server="default-server"
            base-permission="OFBTOOLS" location="webapp/practice" mount-point="/practice"
            app-bar-display="true" />
    </ofbiz-component>
    

    Dies bedeutet, dass das config-Verzeichnis zum classpath hinzugefügt wird damit das Framework auf die Dateien zugreifen kann.

  2. Legen Sie die Datei PracticeUiLabels.xml an und setzen einige Beschriftungen für das UI der Practice-Anwendung (siehe auch ExampleUiLabels.xml ). Beachten Sie bitte, dass der Server neu gestartet werden muss um Änderungen an den UI-Labels anzuzeigen. Für den Anfang werden 2 UI-Labels (Bezeichner) erzeugt.

    <?xml version="1.0" encoding="UTF-8"?>
    <resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    
        <!-- Practice component properties -->
        <property key="PracticeApplication">
            <value xml:lang="en">This is first practice</value>
            <value xml:lang="de">Die erste practice Anwendung</value>
        </property>
        <property key="PracticeCompanyName">
            <value xml:lang="en">OFBiz: Practice</value>
        </property>
        
    </resource>
    

  3. Fürgen Sie die UI-Label Ressource in Ihren main-Decorator-Screen ( CommonScreens.xml ) ein und probieren Sie es aus.

    <property-map resource="PracticeUiLabels" map-name="uiLabelMap" global="true"/>
    

  4. Verwenden Sie die Bezeichner an passenden Stellen. Wichtig: Prüfen Sie bitte immer ob ein UI-Label bereits exisitiert. Vermeiden Sie duplikate. Die Ausgabe der Liste sollte nun folgender Maßen aussehen.

Kapitel 4. Anwendung absichern

Anwendung durch Authentifizierung absichern

  1. Nehmen Sie für Authentifizierung eine Referenz in ExampleMenus.xml .

    Die Optionen können der component://common/webcommon/WEB-INF/common-controller.xml entnommen werden und müssen in unserer eigenen controller.xml eingefügt werden.

    <!- Request Mappings ->
    <!-- Security Mappings -->
     <request-map uri="checkLogin" edit="false">
        <description>Verify a user is logged in.</description>
            <security https="true" auth="false"/>
            <event type="java" path="org.ofbiz.webapp.control.LoginWorker" invoke="checkLogin" />
            <response name="success" type="view" value="main"/>
            <response name="error" type="view" value="login"/>
        </request-map>
        <request-map uri="login">
            <security https="true" auth="false"/>
            <event type="java" path="org.ofbiz.webapp.control.LoginWorker" invoke="login"/>
            <response name="success" type="view" value="main"/>
            <response name="error" type="view" value="login"/>
        </request-map>
        <request-map uri="logout">
            <security https="true" auth="true"/>
            <event type="java" path="org.ofbiz.webapp.control.LoginWorker" invoke="logout"/>
            <response name="success" type="request" value="checkLogin"/>
            <response name="error" type="view" value="main"/>
        </request-map>
    
    						

    Falls Sie die common-controller.xml bereits integriert haben, dann können die Änderungen in der controller.xml entfallen.

  2. Wenn controller.xml auf auth="true" gestellt wurde, werden diese Anfragen durch Authentifikation abgesichert.

    Der Eintrag sollte folgender Maßen aussehen:

    <request-map uri="main">
        <security https="true" auth="true"/>
        <response name="success" type="view" value="main"/>
        <response name="error" type="view" value="main"/>
    </request-map>
    
    						

  3. Jetzt ist es Zeit die Anwendung zu testen. Sie müssen sich nun einloggen (Nutzername: admin, Kennwort: [default: ofbiz]).

    Nun wird es Zeit den Parameter OFBTOOLS , den wir im base-permission Abschnitt in der ofbiz-component.xml Datei vorgenommen haben.

    Führen Sie folgende Schritte aus.

    1. Melden Sie sich beim partymanager ( https://127.0.0.1:8443/partymgr/control/main ) an und stellen Sie sicher, dass der User admin die Berechtigung OFBTOOLS hat.

    2. Geben Sie im "User Login" Feld den Nutzername admin ein und drücken den Button "Nach Party suchen".

    3. Dies führt eine Wildchar ( admin* ) Suche durch und Sie sollten eine Liste von Nutzern sehen. Klicken Sie auf "Details" beim Nutzer "admin".

      Wichtiger Punkt dabei ist, der Nutzer 'Mr. THE PRIVILEGED ADMINISTRATOR' (!! has a partyId admin has multiple login Ids as listed in the User Name(s) form.)

Kapitel 5. Hallo Welt!

Die erste praktische Anwendung (Hallo Welt...)