Schreiben und Debuggen einer Komponente für GWT und Vaadin

    Bild


    Die Google Web Toolkit- und Vaadin-Frameworks funktionieren ziemlich gut, wenn Sie sie nur verwenden. Wenn Sie plötzlich ihre Funktionalität erweitern mussten, dann müssen Sie ernsthaft schwitzen. In diesem Artikel möchte ich erläutern, wie eine einfache Komponente in GWT geschrieben, der Vaadin-Serverteil hinzugefügt und in meiner Anwendung verwendet wird. Ich werde kein vollständig leeres GWT / Vaadin-Projekt erstellen und die GWT-Kompilierung von Anfang an konfigurieren, sondern eine auf CUBA.Plattform basierende Anwendung verwenden , in der ich die Komponente selbst implementiere und sie dann ausprobieren werde. Dies wird zeigen, wie gut alles in diese Anwendung passt. Besonderes Augenmerk möchte ich auf das Debuggen der Komponente legen, da es nicht trivial ist und Entwicklern immer Schwierigkeiten bereitet.

    Ich möchte Sie warnen, dass nicht alles, was in diesem Artikel beschrieben wird, auf GWT und Vaadin zutrifft. Einige der Schritte und Techniken gelten nur im Zusammenhang mit der Verwendung von CUBA.Plattform, wodurch die Einrichtung der Umgebung und einige Routineaktionen erheblich vereinfacht werden.

    Umgebungsvorbereitung


    Wir werden ein leeres Projekt, das in CUBA Studio erstellt wurde, für Experimente verwenden . CUBA - unsere Plattform für die Entwicklung von Geschäftsanwendungen in Java, mit der Sie schnell ein Datenmodell und eine Anwendungsschnittstelle erstellen, die Logik für die Arbeit mit Daten festlegen und Benutzerrechte verwalten können. Im Zentrum der UI-Plattform steht das Vaadin-Webframework, mit dem wir viele interessante Ideen umsetzen können.

    Erstellen Sie zunächst ein GWT-Modul, das in JavaScript kompiliert wird. Führen Sie die Aktion 'Web-Toolkit-Modul erstellen' in Studio aus. Dies ist eine einfache Hilfsoperation, deren manuelle Ausführung nicht sinnvoll ist. Studio generiert einen GWT-Deskriptor für das AppWidgetSet.gwt.xml-Modul, ein Verzeichnis für das Modul und ein leeres Paket und fügt der Beschreibung der build.gradle-Assembly die erforderlichen Aufgaben hinzu.

    Führen Sie im nächsten Schritt die Aktion 'IDE-Projektdateien erstellen oder aktualisieren' aus, um die IntelliJ IDEA-Projektdateien zu generieren, und schreiben Sie den Komponentencode in die IDE.

    Um die Komponente selbst zu programmieren, benötigen wir keine speziellen IDE-Funktionen außer dem Hervorheben von Java-Code. Daher ist es nicht erforderlich, IntelliJ Idea zu verwenden. Wir können auch Eclipse oder Netbeans verwenden. Dank des Google Web Toolkit können wir vertraute Java-Tools verwenden. Dies ist ein großer Vorteil bei der Entwicklung von Großprojekten.

    Schreiben einer Komponente


    Bild

    Die Komponente selbst wird recht einfach sein - ein Bewertungsfeld in Form von 5 Sternen. Dies ist ein Eingabefeld, in dem der Benutzer eine Bewertung mit der Maus auswählt. Es hat einen Status auf dem Server und die Anzeige sollte sich ändern, wenn sie sich ändert.

    Bild

    So sieht unser neues Web-Toolkit-Modul im Idea-Projektfenster aus. Das Root-Paket enthält den GWT-Modul-Deskriptor.
    AppWidgetSet.gwt.xml

    Es erbt das Basismodul CUBA.Platform und ist der Ausgangspunkt des gesamten Client-Teils unserer Anwendung (der im Browser ausgeführt wird). Standardmäßig sollten sich Implementierungen von GWT-Komponenten im Unterpaket 'client' befinden. Erstellen wir das Client-Paket und das darin enthaltene Unterpaket ratingfield.

    Der erste Teil unserer Komponente ist das GWT-Widget. Die RatingFieldWidget-Klasse, die wir in das Web-Toolkit-Modul einfügen:
    RatingFieldWidget.java
    package com.haulmont.ratingsample.web.toolkit.ui.client.ratingfield;
    import com.google.gwt.dom.client.DivElement;
    import com.google.gwt.dom.client.SpanElement;
    import com.google.gwt.dom.client.Style.Display;
    import com.google.gwt.user.client.DOM;
    import com.google.gwt.user.client.Event;
    import com.google.gwt.user.client.ui.FocusWidget;
    import java.util.ArrayList;
    import java.util.List;
    // класс GWT виджета
    public class RatingFieldWidget extends FocusWidget {
        private static final String CLASSNAME = "ratingfield";
         // API для реакции на клики
        public interface StarClickListener {
                void starClicked(int value);
        }
        protected List stars = new ArrayList(5);
        protected StarClickListener listener;
        protected int value = 0;
        public RatingFieldWidget() {
            DivElement container = DOM.createDiv().cast();
            container.getStyle().setDisplay(Display.INLINE_BLOCK);
            for (int i = 0; i < 5; i++) {
                SpanElement star = DOM.createSpan().cast();
                // Добавляем элемент звезды в контейнер
                DOM.insertChild(container, star, i);
                // Подписываемся на событие ONCLICK
                DOM.sinkEvents(star, Event.ONCLICK);
                stars.add(star);
            }
            setElement(container);
            setStylePrimaryName(CLASSNAME);
        }
        // главный метод обработки событий в виджетах GWT
        @Override
        public void onBrowserEvent(Event event) {
            super.onBrowserEvent(event);
            switch (event.getTypeInt()) {
                // Реагируем на события ONCLICK
                case Event.ONCLICK:
                    SpanElement element = event.getEventTarget().cast();
                    // только если клик по звезде
                    int index = stars.indexOf(element);
                    if (index >= 0) {
                        int value = index + 1;
                        // устанавливаем внутреннее значение
                        setValue(value);
                        // уведомляем интересующихся
                        if (listener != null) {
                            listener.starClicked(value);
                        }
                    }
                    break;
                }
        }
        // Понадобиться если на сервере зададут другой primaryStyleName
         // это часто случается при наследовании классов компонентов
        @Override
        public void setStylePrimaryName(String style) {
            super.setStylePrimaryName(style);
            for (SpanElement star : stars) {
                star.setClassName(style + "-star");
            }
            updateStarsStyle(this.value);
    }
    // Позволим изменять состояние стороннему коду
    public void setValue(int value) {
            this.value = value;
            updateStarsStyle(value);
        }
        // обновляем визуальное представление
        private void updateStarsStyle(int value) {
                for (SpanElement star : stars) {
                    star.removeClassName(getStylePrimaryName() + "-star-selected");
                }
                for (int i = 0; i < value; i++) {
                    stars.get(i).addClassName(getStylePrimaryName() + "-star-selected");
                }
        }
    }

    Ein Widget ist eine isolierte Klasse, die für das Anzeigen und Reagieren auf Ereignisse verantwortlich ist. Er muss nichts über den Server wissen, sondern definiert nur die Schnittstellen für die Arbeit damit. In unserem Fall ist dies die Methode setValue und die StarClickListener-Schnittstelle.

    Es ist erwähnenswert, dass der gesamte Widget-Code keine einzige JavaScript-Zeile enthält, was für große und komplexe Komponenten ziemlich gut ist. Vergessen Sie jedoch nicht, dass dieser Java-Code in JavaScript kompiliert wird und viele Teile der Java-Standardbibliothek, z. B. Reflection und I / O, möglicherweise nicht verfügbar sind (vollständige Informationen zur Kompatibilität finden Sie hier: www.gwtproject.org/doc/latest/RefJreEmulation.html) )

    Wir bestimmen das Aussehen


    Wie Sie vielleicht bemerkt haben, gibt es im Widget-Code keine Verweise auf das Erscheinungsbild, es sei denn, Sie weisen den Schlüsselelementen Stilnamen zu. Diese Technik wird ständig bei der Entwicklung von Komponenten verwendet und ermöglicht es Ihnen, das Erscheinungsbild in CSS anhand von Stilkombinationen zu bestimmen.

    Erstellen Sie zunächst Stildateien, um das Erscheinungsbild unserer Komponente zu bestimmen. Dazu können wir die Aktion 'Themenerweiterung erstellen' für das Thema 'Halo' verwenden. In diesem Thema werden FontAwesome-Schriftzeichen anstelle von Symbolen verwendet, die wir verwenden werden. Studio erstellt leere SCSS-Dateien für unsere Experimente im Themenverzeichnis des Webmoduls.

    Es ist üblich, die Stile jeder Komponente in eine separate Datei componentname.scss im Verzeichnis components / componentname im SCSS-Zusatzformat zu unterteilen:
    ratingfield.scss
    @mixin ratingfield($primary-stylename: ratingfield) {
      .#{$primary-stylename}-star {
        font-family: FontAwesome;
        font-size: $v-font-size--h2;
        padding-right: round($v-unit-size/4);
        cursor: pointer;
        &:after {
              content: '\f006'; // 'fa-star-o'
        }
      }
      .#{$primary-stylename}-star-selected {
        &:after {
              content: '\f005'; // 'fa-star'
        }
      }
      .#{$primary-stylename} .#{$primary-stylename}-star:last-child {
        padding-right: 0;
      }
      .#{$primary-stylename}.v-disabled .#{$primary-stylename}-star {
        cursor: default;
      }
    }

    Dann ist eine solche Datei in der Hauptthemadatei enthalten
    halo-ext.scss
    @import "../halo/halo";
    @import "components/ratingfield/ratingfield";
    /* Define your theme modifications inside next mixin */
    @mixin halo-ext {
      @include halo;
      @include ratingfield;
    }

    Ein paar Worte zu SCSS. Dies ist ein Beschreibungsformat im CSS-Stil für die Verwendung von Variablen, Verunreinigungen und berechneten Werten. Es wird in vielen Webframeworks aktiv verwendet, in Vaadin 7 ist es das Grundformat für Anwendungsthemen. In der CUBA.Platform-Anwendung können wir dieses Format einfach verwenden, da Studio die schmutzige Arbeit der Organisation der Zusammenstellung von SCSS-Themen übernimmt.

    Das Format der Beschreibung in Form einer Verunreinigung hilft uns, wenn die Komponente Erben mit einem anderen Primärstylenamen hat. Wir aktivieren einfach Vorfahrenstile mit dem SCSS- Include .

    Für unsere Sterne verwenden wir zwei FontAwesome-Glyphen - 'fa-star' und 'fa-star-o'. CSS selbst ist recht einfach und enthält nur Sternsymbole in zwei Zuständen und einen Mauszeiger für sie.

    Wählen Sie Halo auf der Seite Projekteigenschaften in CUBA.Studio aus, um die Themen in der Anwendung zu wechseln.

    Fügen Sie die Serverseite hinzu


    Bis zu diesem Punkt konnten wir das Widget verwenden, das wir in einer GWT-Anwendung geschrieben haben, da es in keiner Weise vom Server abhing. Lassen Sie uns nun über das Vaadin-Framework und sein serverorientiertes Modell sprechen. Es hat ein paar Features:

    - alle Zustand der Komponenten und Eingabefelder auf dem Server gespeichert und kann auch nach einer vollständigen Aktualisierung der Seite oder eine offene Verbindung zum Server wiederhergestellt werden
    - alle nützlichen Anwendungscode, mit Ausnahme der Client - Seite auf dem Server ausgeführt wird

    Das heißt Vaadin Komponenten von Developer versteckt sind Die Art und Weise, wie sie im Browser arbeiten und der unvorsichtige Java-Entwickler sieht HTML / CSS nie (naja oder fast nie, sonst ist es sogar praktisch, Komponenten zu schreiben).

    Erstellen Sie das Paket com.haulmont.ratingsample.web.toolkit.ui im ​​Webmodul. Darin platzieren wir den Code unserer Komponente RatingField. Wir erben eine Klasse von der Vaadin AbstractField-Klasse, die die grundlegende Logik der Eingabefelder definiert.

    Die wichtigsten Serverkomponenten der Vaadin-Komponente:

    1) Die RatingField-Komponentenklasse definiert die API für den Servercode, verschiedene Get / Set-Methoden für die Arbeit, Ereignis-Listener und die Verbindung von Datenquellen. Anwendungsentwickler verwenden in ihrem Code immer die Methoden dieser Klasse.
    RatingField.java
    package com.haulmont.ratingsample.web.toolkit.ui;
    import com.haulmont.ratingsample.web.toolkit.ui.client.RatingFieldServerRpc;
    import com.haulmont.ratingsample.web.toolkit.ui.client.RatingFieldState;
    import com.vaadin.ui.AbstractField;
    // Наше поле будет иметь тип значения Integer
    public class RatingField extends AbstractField {
        public RatingField() {
                // регистрируем особую реализацию интерфейса, которая будет вызвана при запросе с клиента
            registerRpc(new RatingFieldServerRpc() {
                @Override
                public void starClicked(int value) {
                    setValue(value, true);
                }
            });
        }
        // тип значения поля
        @Override
        public Class getType() {
                return Integer.class;
        }
        // определяем свой класс для состояния
        @Override
        protected RatingFieldState getState() {
                return (RatingFieldState) super.getState();
        }
        @Override
        protected RatingFieldState getState(boolean markAsDirty) {
                return (RatingFieldState) super.getState(markAsDirty);
        }
        // при вызове setValue из прикладного кода нужно обновить состояние
        @Override
        protected void setInternalValue(Integer newValue) {
            super.setInternalValue(newValue);
                if (newValue == null) {
                    newValue = 0;
                }
                getState().value = newValue;
        }
    }

    2) Die Statusklasse RatingFieldState ist dafür verantwortlich, welche Daten zwischen dem Client und dem Server gesendet werden. Es definiert öffentliche Felder, die auf dem Server automatisch serialisiert und auf dem Client deserialisiert werden.
    RatingFieldState.java
    package com.haulmont.ratingsample.web.toolkit.ui.client;
    import com.vaadin.shared.AbstractFieldState;
    public class RatingFieldState extends AbstractFieldState {
        {   // изменим главное имя стиля компонента
                primaryStyleName = "ratingfield";
        }
        // объявим поле для нашего значения
        public int value = 0;
    }

    3) RatingFieldServerRpc-Schnittstelle - Definiert die Server-API für den Client-Teil. Die Methoden können vom Client mithilfe des in Vaadin integrierten Remote Procedure Call-Mechanismus aufgerufen werden. Wir implementieren diese Schnittstelle in der Komponente selbst. In diesem Fall rufen wir einfach die setValue-Methode unseres Feldes auf.
    RatingFieldServerRpc.java
    package com.haulmont.ratingsample.web.toolkit.ui.client;
    import com.vaadin.shared.communication.ServerRpc;
    public interface RatingFieldServerRpc extends ServerRpc {
        // метод будет вызываться в клиентском коде
        void starClicked(int value);
    }

    Der wichtige Punkt ist, dass sich die Statusklassen und der rpc im Unterpaket 'client' befinden sollten, damit die zähen Pfoten des GWT-Compilers leicht zu ihnen gelangen, um ihre JavaScript-Darstellung für den Clientcode zu erstellen. Darüber hinaus sollten Klassen keinen Code verwenden, der nicht von GWT kompiliert werden kann.

    Jetzt ist es an der Zeit, unseren Client-Code der Serverseite zuzuordnen. Konnektorklassen spielen in Vaadin diese Rolle. Sie werden neben Widget-Klassen platziert. Die Connector-Klasse wird von Connect (ComponentName.class) mit Anmerkungen versehen , und die Korrespondenz des Client-Teils des Servers wird festgelegt:
    RatingFieldConnector.java
    package com.haulmont.ratingsample.web.toolkit.ui.client.ratingfield;
    import com.haulmont.ratingsample.web.toolkit.ui.RatingField;
    import com.haulmont.ratingsample.web.toolkit.ui.client.RatingFieldServerRpc;
    import com.haulmont.ratingsample.web.toolkit.ui.client.RatingFieldState;
    import com.vaadin.client.communication.StateChangeEvent;
    import com.vaadin.client.ui.AbstractFieldConnector;
    import com.vaadin.shared.ui.Connect;
    // Связываем наш коннектор с серверной реализацией RatingField
    // наследуем коннектор для AbstractField
    @Connect(RatingField.class)
    public class RatingFieldConnector extends AbstractFieldConnector {
        // мы будем использовать виджет RatingFieldWidget
        @Override
        public RatingFieldWidget getWidget() {
                RatingFieldWidget widget = (RatingFieldWidget) super.getWidget();
            if (widget.listener == null) {
    widget.listener = new RatingFieldWidget.StarClickListener() {
                    @Override
                    public void starClicked(int value) {
                    getRpcProxy(RatingFieldServerRpc.class).starClicked(value);
                    }
                };
            }
            return widget;
        }
        // наш тип состояния - RatingFieldState
        @Override
        public RatingFieldState getState() {
                return (RatingFieldState) super.getState();
        }
        // реагируем на изменение состояния на сервере
        @Override
        public void onStateChanged(StateChangeEvent stateChangeEvent) {
            super.onStateChanged(stateChangeEvent);
          // если значение на сервере изменилось, обновляем виджет
            if (stateChangeEvent.hasPropertyChanged("value")) {
                getWidget().setValue(getState().value);
            }
        }
    }

    Probelauf


    Um dies alles in der Praxis zu versuchen, führen wir einige vorbereitende Schritte durch:

    1) Erstellen Sie eine Datenbank für die Anwendung über das Studio-Menü: Ausführen - Datenbank erstellen
    2) Erstellen Sie einen Bildschirm zum Platzieren der Komponente im Webmodul:

    Bild

    3) Fügen Sie dem Anwendungsmenü einen Bildschirm hinzu: Hauptmenü - Bearbeiten

    Bild

    4) Fahren wir nun mit der Bearbeitung unseres Bildschirms in der IDE fort.
    Wir brauchen einen Container für unsere Komponente, deklarieren wir ihn im Screen XML:
    rating-screen.xml

    Öffnen wir die Rating Controller-Klasse RatingScreen.java und fügen den Code zum Platzieren unserer Komponente auf dem Bildschirm hinzu:
    RatingScreen.java
    package com.haulmont.ratingsample.web;
    import com.haulmont.ratingsample.web.toolkit.ui.RatingField;
    import com.haulmont.cuba.gui.components.AbstractWindow;
    import com.haulmont.cuba.gui.components.BoxLayout;
    import com.haulmont.cuba.web.gui.components.WebComponentsHelper;
    import javax.inject.Inject;
    import java.util.Map;
    public class RatingScreen extends AbstractWindow {
        @Inject
        private BoxLayout container;
        @Override
        public void init(Map params) {
            super.init(params);
            // используем API CUBA чтобы добраться до Vaadin реализации контейнера:
            com.vaadin.ui.Layout containerLayout = WebComponentsHelper.unwrap(container);
            // используем наш компонент как в обычном Vaadin приложении:
            RatingField field = new RatingField();
            field.setCaption("Rate this!");
            containerLayout.addComponent(field);
        }
    }

    Das Web-Modul unterstützt perfekt die Integration von Vaadin-Komponenten, sowohl von Drittanbietern als auch selbst geschrieben. Sie können sie direkt verwenden, als würden Sie eine Bewerbung für pure Vaadin schreiben.

    Wir starten die Anwendung von Studio aus: Starten Sie den Anwendungsserver und rufen Sie http: // localhost: 8080 / app auf, um das Ergebnis zu sehen:

    Bild

    Wir freuen uns über die voll funktionsfähige Komponente, die wir jetzt aus unserem Java-Code auf dem Server verwenden können. Der gesamte Code ist für die Verwendung in jeder Vaadin-Anwendung geeignet.

    Den vollständigen Anwendungscode finden Sie hier: github.com/Haulmont/ratingsample.git

    Debuggen im Browser


    Wir werden nur das Debuggen von Widget-Code betrachten, da das Debuggen von Java-Komponentencode auf dem Server recht einfach ist.

    Das Debuggen von GWT-Code ist völlig untrivial und erfordert Genauigkeit. Verwenden Sie zum Debuggen den SuperDevMode-Modus. Ihr Projekt muss mit GWT 2.5.1 oder höher erstellt werden. In diesem Modus wird Java-Code in einem Browser auf JavaScript-Code abgebildet (Quell-Maps siehe developer.chrome.com/devtools/docs/javascript-debugging#source-maps ). Das heißt, Sie sehen und debuggen Java-Code im Browser, jedoch mit einigen Einschränkungen.

    Das Arbeitsschema ist wie folgt:
    1. Sie starten den Server com.google.gwt.dev.codeserver.CodeServer und geben der Browserseite die Entsprechung von JS-Code und Java-Code sowie die Erfassung Ihres Widgets beim Aktualisieren der Seite
    2. Öffnen Sie eine Anwendung mit Optionen? Debug & Superdevmode
    3. Entwicklertools konfigurieren, F12, in der unteren rechten Ecke befindet sich eine Schaltfläche zum Öffnen der Einstellungen. Aktivieren Sie die Option Quellkarten aktivieren
    4. Aktualisieren Sie die Seite, und öffnen Sie die Registerkarte Quellen in den Entwicklertools. Alle Java-Klassen von GWT-Widgets sollten dort angezeigt werden. Im Chrome-Debugger können Sie Haltepunkte festlegen, Variablen überwachen und Ausdrücke ausführen.
    5. Wenn Sie den Widget-Code im Projekt ändern, genügt es, die Seite zu aktualisieren. Der Widget-Satz wird neu erstellt und vom Browser abgerufen. Auf diese Weise können Sie Änderungen des Widget-Codes sofort erkennen, was die Entwicklung erheblich beschleunigt.

    Wir versuchen, alles in unserem Projekt auszuführen:
    1) Um diesen Modus zu starten, müssen wir das Laufzeitabhängigkeits-ServletApi für das Web-Toolkit-Modul in der Datei build.gradle hinzufügen:
    build.gradle
    ...
    configure(webToolkitModule) {
        dependencies {
            ...
            runtime(servletApi)
        }
    ...

    2) Führen Sie in Studio die Aktion "IDE-Projektdateien erstellen oder aktualisieren" aus, damit Idea eine neue Abhängigkeit erkennt.
    3) Erstellen Sie in Idea eine neue Startkonfiguration mit dem Anwendungstyp und den folgenden Parametern

    : Hauptklasse : com.google.gwt.dev.codeserver.CodeServer
    VM Optionen: -Xmx512M
    Klassenpfad des Moduls verwenden: app-web-toolkit
    Programmargumente: -workDir C: \ Benutzer \ yuriy \ work \ ratingsample \ build \ tomcat \ webapps \ app \ VAADIN \ widgetsets -src C: \ Benutzer \ yuriy \ work \ ratingsample \ modules \ web \ src -src C: \ Users \ yuriy \ work \ ratingsample \ modules \ web-toolkit \ src com.haulmont.ratingsample.web.toolkit.ui.AppWidgetSet

    Pfade zum Erstellen der Verzeichnisse \ tomcat \ webapps \ app \ VAADIN \ widgetsets, modules \ web \ src und modules \ web-toolkit \ src müssen durch Ihre eigenen ersetzt werden.

    Bild

    4) In Studio ausführen: Starten Sie den Anwendungsserver.
    5) Führen Sie die zuvor erstellte GWT-Konfiguration in Idea aus.
    6) Gehen Sie zu der Adresse http: // localhost: 8080 / app? Debug & superdevmode.
    7) Öffnen Sie DevTools in Chrome und sehen Sie Ihren Java-Code:

    Bild

    Der Vorteil dieser Methode ist, dass keine spezielle IDE-Unterstützung erforderlich ist, dass sie schnell funktioniert und dass Sie Code direkt im Browser debuggen können. Zu den Nachteilen gehören die Tatsache, dass Sie während des Debuggens nicht auf den Java-Code zugreifen können, sowie Haltepunkte unter Java-Bedingungen, und dies ist irgendwie ungewöhnlich. Es gibt auch ein dickes Minus - alte Browser wissen überhaupt nicht, wie man Maps erzeugt, was das normale Debuggen erschwert.

    Anstelle einer Schlussfolgerung


    GWT ist ein sehr starkes und entwickeltes Webframework, das in den letzten Jahren von einer großen Anzahl von Entwicklern auf der ganzen Welt aktiv eingesetzt wurde. Google vergisst seine Idee nicht und nutzt sie aktiv. Zuletzt veröffentlichten sie Gmail Inbox ( http://gmailblog.blogspot.ru/2014/11/going-under-hood-of-inbox.html ), für das GWT intensiv genutzt wird Web-Oberfläche.

    Vaadin bleibt auch nicht zurück und ist jetzt eine der besten serverseitigen Optionen für GWT. Mit dem serverbasierten Modell können Sie schnellere, wartungsfreundlichere Anwendungen entwickeln und sich weniger Gedanken über die Datensicherheit machen. Die Komplexität der Verbesserung der Funktionalität von GWT und Vaadin ist ziemlich isoliert und sollte nicht erschreckt werden. Die Vorteile dieser Technologien für die Entwicklung decken alle ihre Nachteile ab.

    Wir setzen Vaadin seit über 5 Jahren aktiv ein und sind davon überzeugt. Ich rate jedem, dies als Hauptgrundlage für die Erstellung von Webanwendungen zu betrachten, insbesondere für Unternehmen.

    Vielen Dank für Ihre Aufmerksamkeit!

    Jetzt auch beliebt: