$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
Inhaltsverzeichnis
Inhaltsverzeichnis
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
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
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.
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>
Über die
ofbiz-component.xml
Datei wird OFBiz mitgeteilt wo die Ressourcen sind und welche
Elemente zum Classpath hinzuzufügen sind.
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"/>
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.
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.
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.
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.
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.
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>
Das Gerüst für die Fehlerbehandlung
Legen Sie ein neues Verzeichnis
error
in folgendem Pfad an:
hot-deploy/practice/webapp/practice/
.
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.
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.
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 .
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).
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.
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.
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.
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.
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.
Inhaltsverzeichnis
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
.
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>
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?
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>
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>
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ü.
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.
Fügen Sie einen weiteren Punkt zum Menü in der
PracticeMenus.xml
hinzu.
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>
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>
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"
).
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>
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>
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"/>
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.
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.
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>
Den
Decorator
haben Sie bereits in den
CommonPracticeDecorator
screen (
PracticeScreens.xml
) eingefügt.
Inhaltsverzeichnis
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.
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.
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>
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"/>
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.
Inhaltsverzeichnis
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.
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>
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.
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.
Geben Sie im "User Login" Feld den Nutzername
admin
ein und drücken den Button "Nach Party suchen".
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.)
Inhaltsverzeichnis