1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
|
---
title: Vaadin Tutorial For Swing Developers
order: 8
layout: page
---
[[a-hitchhikers-guide-to-convert-aswing-appto-modern-web-app]]
= A hitchhiker's guide to convert a Swing app to modern web app
[[intro]]
Intro
~~~~~
As expressed by Pete Hunt (Facebook, React JS) in JavaOne 2014 Web
Framework Smackdown, if you would be creating a UI toolkit, from a
scratch, it would look nothing like a
https://en.wikipedia.org/wiki/Document_Object_Model[DOM]. Web
technologies indeed are not designed for application development, but
rich text presentation. Markup based presentation has proven to be
superior for more static content like web sites, but _applications_ are
a bit different story. In the early stages of graphical UIs on
computers, UI frameworks didn’t by accident form into “component based”
libraries. Those UI libraries have developed during the decades, but the
the basic concept of component based UI framework is still the most
powerful way to create _applications_.
But Swing, SWT, Qt and similar desktop UI frameworks have one major
problem compared to web apps: they require you to install special
software on your client machine. As we have learned during the internet
era, this can be big problem. Users have lots of different kinds of
applications that they use nowadays and installing all of them and
especially maintaining those will become a burden for your IT
department.
Browser plugins like Java’s Applet/Java WebStart support (and there
Swing or JavaFX) and Flash are the traditional workarounds to avoid
installing software locally for workstations. But famous security holes
in those, especially with outdated software, may become a huge problem
and your IT department is nowadays most likely against installing any
kind of third party browser plugins. For them it is much easier to just
maintain one browser application. This is one of the fundamental reasons
why pure web apps are conquering even most complex application domains
nowadays.
[[welcome_to_the_8220wonderful8221_world_of_web_apps]]
Welcome to the “wonderful” world of web apps
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
image:img/howvaadinworks2.png[How Vaadin works] Even
for experienced desktop developers it may be a huge jump from the
desktop world to the web development. Developing web applications is
much trickier than developing basic desktop apps. There are lots of
things that makes things complicated, such as client-server
communication, the markup language and CSS used for display, new
programming language for the client side and client-server communication
in many different forms (basic http, ajax style requests, long polling,
web sockets etc.). The fact is that, even with the most modern web app
frameworks, web development is not as easy as building desktop apps.
Vaadin Framework is an open source Java framework and is the closest
thing to the component based Swing UI development in the mainstream web
app world. Vaadin is a component based UI framework that tries to make
web development as easy as traditional desktop development, maximizing
developers’ productivity and the quality of the produced end user
experience. In a Vaadin application the actual UI logic, written by you,
lives in the server’s JVM. Instead of browser plugins, Vaadin has a
built-in “thin client” that renders the UI efficiently in browsers. The
highly optimized communication channel sends only the stuff that is
really visible on user’s screen to thin client. Once the initial
rendering has been done, only deltas, in both way, are transferred
between the client and the server.
The architecture of Vaadin Framework provides you an abstraction for the
web development challenges, and most of the time you can forget that
your are building a web application. Vaadin takes care of handling all
the communication, html markup, css and browser differences - you can
concentrate all your energy on your domain problems with clean Java
approach and take advantage of your experience from the desktop
applications.
Vaadin uses GWT to implement its “thin client” running in the browser.
GWT is another bit similar tool for web development, and its heart is
its Java to JavaScript “compiler”. GWT also has a Swing like UI
component library, but in GWT the Java code is compiled into JavaScript
and executed in the browser. The compiler supports only a subset of Java
and the fact that it is not running in JVM causes some other
limitations, but the concepts are the same in it as well. Running your
code in the browser as a white box also has some security implications.
[[architectural_differences_you_should_notice]]
Architectural differences you should notice
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Every architectural decision has its pros and consequences and so does
switching from Swing to Vaadin in your UI layer.
[[one_application_instance_many_users]]
One application instance, many users
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The first thing you’ll notice is that you are now developing your UI
right next to your data. Pretty much all modern business apps, both web
and desktop apps, save their data somehow to a central server. Often the
data is “shielded” with middleware layer, with e.g. EJBs. Now that you
move to Vaadin UI, the EJB, or whatever the technology you use in your
“backend”, is “closer”. It can often be run in the very same application
server as your Vaadin UI, making some hard problems trivial. Using a
local EJB is both efficient and secure.
Even if you’d still use a separate application server for your EJBs,
they are most probably connected to UI servers using a fast network that
can handle chatty connection between UI and business layers more
efficiently than typical client server communication - the network
requirements by the Vaadin thin client are in many cases less demanding,
so your application can be used over e.g. mobile networks.
Another thing developers arriving from desktop Java to Vaadin will soon
notice that fields with “static” keyword are quite different in the
server world. Many desktop applications use static fields as “user
global” variables. In Java apps running in server, they are “application
global”, which is a big difference. Application servers generally use a
class loader per web application (.war file), not class loader per user
session. For “user global” variables, use fields in your UI class,
https://vaadin.com/api/com/vaadin/server/VaadinSession.html[VaadinSession],
http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSession.html[HttpSession]
or e.g.
http://docs.oracle.com/javaee/7/api/javax/enterprise/context/SessionScoped.html[@SessionScoped]
CDI bean.
Web applications in general will be much cheaper for IT departments to
maintain. They have been traditionally run in company’s internal
servers, but the trend of the era is hosting them in PaaS services, in
the “cloud”. Instead of maintaining the application in each users’
workstation, updates and changes only need to be applied to the server.
Also all data, not just the shared parts, is saved on the server whose
backups are much easier to handle. When your user’s workstation breaks,
you can just give him/her a replacement and the work can continue.
[[memory_and_cpu_usage_is_centralized_to_server]]
Memory and CPU usage is centralized to server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
On the negative side is the fact that some of the computing previously
done by your users workstation is now moved to the server. The CPU hit
is typically negligible, but you might face some memory constraints
without taking this fact into account. On the other hand, the fact that
the application memory and processing happens now mostly on the server,
might be a good thing. The server side approach makes it possible to
handle really complex computing tasks, even with really modest handheld
devices. This is naturally possible with Swing and central server as
well, but with Vaadin approach this comes a free bonus feature.
A typical Vaadin business app consumes 50-500kB of server memory per
user, depending on your application characteristics. If you have a very
small application you can do with smaller number and if you reference a
lot of data from your UI, which usually makes things both faster and
simpler, you might need even more memory per user.
The per user memory usage is in line with e.g. Java EE standard JSF. If
you do some basic math you can understand this isn’t an issue for most
typical applications and modern application servers. But, in case you
create an accidental memory leak in application code or a carelessly
load the whole database table into memory, the memory consumption may
become an issue earlier than with desktop applications. Accidentally
referencing million basic database entities from a user session will
easily consume 100-200MB of memory per session. This might still be
tolerable in desktop applications, but if you have several concurrent
users, you’ll soon be in trouble.
The memory issues can usually be rather easily solved by using paging or
by lazy loading the data from the backend to UI. Server capacity is also
really cheap nowadays, so buying a more efficient server or clustering
your application to multiple application servers is most likely much
cheaper than by making compromises in your architectural design. But in
case each of your application users need to do some heavy analysis with
huge in-memory data sets, web applications are still not the way to go
for your use case.
If your applications memory usage is much more important than its
development cost (read: you are trying to write next GMail), Vaadin
framework might not be the right tool for your. If you still want to go
to web applications, in this scenario you should strive for completely
(server) stateless application and keep your UI logic in browsers.
http://www.gwtproject.org[GWT] is a great library for this kind of
applications.
[[basic_component_usage]]
Basic component usage
~~~~~~~~~~~~~~~~~~~~~
Basic component usage is something where you’ll really find yourself
comfortable from the day one. APIs are not exactly the same, but they
share the principle. Lets look at a very basic example, lets create a
textfield and a button and just throw the textfield value on button
click to sysout for debugging.
[source,java]
....
final JTextField textField = new JTextField();
JButton button = new JButton();
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("You typed: " + textField.getText());
}
});
add(textField);
add(button);
....
… and the very same thing in Vaadin application looks like this:
[source,java]
....
final TextField textField = new TextField();
Button button = new Button();
button.addClickListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
System.out.println("You typed: " + textField.getValue());
}
});
addComponent(textField);
addComponent(button);
....
No need to explain what happens in either of the cases ;-) Typically
when Swing developers start using Vaadin, in basic component usage they
find the methods they are looking for quickly with the help of their
favorite IDE.
Vaadin http://demo.vaadin.com/sampler/[Sampler] is a demo application
that contains examples of the core components with source code usage
example and references to JavaDocs. It is the favorite reference for
many Vaadin developers. Naturally you can also refer to plain JavaDocs
and our Book of Vaadin, the complete reference manual for Vaadin.
[[event_handling_and_event_dispatching_thread]]
Event handling and Event dispatching thread
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Like most typical desktop GUI libraries, Swing serializes all access to
UI via so called event dispatching thread. It fires event listeners you
hook to components and if you wish to modify the UI from another thread,
you submit your UI changing tasks to it with
SwingUtilities.invokeAndWait(Runnable) or
SwingUtilities.invokeLater(Runnable).
In Vaadin there is no similar thread, but naturally parallel UI access
needs to be avoided. Vaadin uses UI (~ browser tab/window) level
locking. Like with Swing apps, the code executed by framework (UI init,
event listeners) is “thread safe”” by default. These code blocks are
usually run in Servlet containers thread that is handling an
HTTP/Websocket request. In case you need to modify a UI from any other
thread, you should use _UI.getCurrent().access(Runnable)_ or
_UI.getCurrent().accessSynchronously(Runnable)_ to ensure there is no
parallel access.
[[application_bootstrap]]
Application bootstrap
~~~~~~~~~~~~~~~~~~~~~
A Vaadin application is basically a
http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html[HttpServlet]
behind the scenes. In portal environment its is a Portlet. Bootstrapping
a Vaadin application depends a bit on the execution environment and used
helper libraries.
In Swing applications your execution typically starts from the iconic
https://github.com/mstahv/ejb-swing-vaadin-crud/blob/master/desktop/src/main/java/org/vaadin/swingersclub/SwingApplication.java#L49-L52[main
method] or from an Applet’s init method. In simple Vaadin Servlet
deployment the similar entry point to your code is _UI_ class and its
_init_ method. The counterpart for UI class is browser window or browser
tab. If your Vaadin application is “embedded” into another page, you
should consider it as the “slot” in that host page. One servlet can
handle multiple UIs, mapped to different URLs, but typically you just
have one per application.
A code snippet below is an example of low level hello world Vaadin
application bootstrap, it introduces a Vaadin servlet as a nested class
using the @WebServlet annotation and a Vaadin UI mapped to it:
[source,java]
....
public class MyUI extends UI {
@WebServlet(urlPatterns = "/*", name = "MyUIServlet")
@VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
public static class MyUIServlet extends VaadinServlet {
}
@Override
protected void init(VaadinRequest vaadinRequest) {
setContent(new Label("Hello World!"));
}
}
....
But, like with non trivial Swing apps, you might want to delegate some
of this low level stuff to a framework that takes care of servlet, setup
and UI mapping. It is highly suggested to use e.g.
https://vaadin.com/javaee/[Java EE environment] with Vaadin CDI add-on
or https://vaadin.com/spring/[Spring] as a basis for your application.
In these cases you typically end up having different application views
as class files and container specific annotations to hint how those
should be served for the end users. In the example we are using
cdi-helpers add-on that also gives you a basic top level navigation and
application layout for free.
The following class will be automatically visible in our applications
menu. Not that the screenshot also shows some other views but our “about
view”.
[source,java]
....
@CDIView("about")
public class AboutView extends VerticalLayout implements View {
@PostConstruct
void init() {
addComponent(new Label("Hello World !"));
}
@Override
public void enter(ViewChangeListener.ViewChangeEvent viewChangeEvent) {
}
}
....
image:img/helloworldview.png[image]
_Screenshot of the hello world view_
[[laying_out_components]]
Laying out components
~~~~~~~~~~~~~~~~~~~~~
In Swing you are using different Layout implementations that take care
of positioning components in JPanel’s sub classes. You will find
similarly named Layout interface in Vaadin as well, but there is a
conceptual difference. In Vaadin Layout is just a normal component that
whose main feature is to contain other components.
[[layouts_in_vaadin]]
Layouts in Vaadin
^^^^^^^^^^^^^^^^^
As you probably have learned while working with Swing applications,
building layouts is generally a rather complex topic. We believe we have
come up with really powerful and logical API, but understanding the
basic concepts about layouts is something you really want to do before
building any non-trivial application. Check out at least a nice
http://youtu.be/7UxEfaQq4EQ?list=PLcRrh9hGNalnmA1mbDS0NBuq6N3Mnw2u1[tutorial
style webinar] we had last year and also refer to our manual.
Most commonly used Layout implementations are VerticalLayout,
HorizontalLayout and GridLayout. By combining and configuring them
intelligently you can achieve pretty much everything. CssLayout is also
commonly used, due to its simplicity in browsers DOM. If you plan to
theme your application it will be the favorite of your CSS artist, but
it works also without any CSS at all, pretty much like FlowLayout in
Swing, although you need to use some CSS if you want the flow to be
horizontal.
One thing related to Layouts is that each component in Vaadin has a
caption and an icon. Most often these properties are handled by the
layout and different layouts handle them in different ways. For example
the FormLayout places caption and icon on the left side of the component
as where HorizontalLayout and VerticalLayout place captions above the
component. Naturally you don’t need to use the built in captions (and
icons), but you can use Label components instead, like with Swing
applications, and manually place them in the desired location.
To get an overview of Layout components in Vaadin, you can also take a
quick overview of them via our
http://demo.vaadin.com/sampler/#ui/layout[Sampler application].
[[custom_layouts]]
Custom layouts
^^^^^^^^^^^^^^
The fact that Layout is just a component that contains other components
gives us some nice flexibility. They can easily be reused to make a more
domain specific classes using composition and, in case you can also
master some browser development, it is easy to build completely new
layouts. Even if you want to stick on the safe JVM side, the
http://vaadin.com/directory[Directory] contains lots of different kind
of layout implementations for custom purposes. Check e.g. BorderLayout
(you can probably guess how it works ;-) ), ColumnLayout,
DragAndDropLayouts, PortalLayouts and the handy layout helpers in
Viritin.
There is also a CustomLayout component in the core distribution, for
which a better describing name would probably be “HtmlTemplateLayout”.
From that you can figure out what it does. If you have a skilled
“designer” in your team who masters html and css, you can use his HTML
templates. Into the markup you just need to specify the “slots” where
you want to place Vaadin components.
[[visual_view_composition]]
Visual view composition
~~~~~~~~~~~~~~~~~~~~~~~
Some Swing developers swear for the name of handwritten layouts and
complete control of your views. Another tribe likes to draft the UIs
with visual tools and then wire it to the application logic using Java.
The same thing in Vaadin world.
image:https://vaadin.com/documents/10187/8663276/designersetup/c3ddcc59-0b6f-40f2-8bb2-456261b5d7a3?t=1418989464957[image]
Vaadin Eclipse plugin comes with https://vaadin.com/designer[Vaadin
Designer] that lets you design your UIs in “WYSIWYG” manner. You can add
code manually to your visually designed classes and then later return to
visual positioning if you want.
The https://vaadin.com/designer[latest version] changed the “master
data” of the layout to be based on HTML5 style markup. This may sound
like a weird decision for some experienced Java developers, but the idea
is that your layout designs and visual appearance can also be edited by
less technical graphical artists, who don’t know anything about Java
programming, but can do amazing tricks with graphics, html, css and
typography. Named components will be naturally available via
auto-generated classes, so customization and wiring to other parts of
your application will still be plain old Java development that you
already master. It is just the auto-generated Java parts that we changed
into markup like format.
[[binding_data_to_components]]
Binding data to components
~~~~~~~~~~~~~~~~~~~~~~~~~~
https://vaadin.com/book/-/page/datamodel.html#datamodel[Binding data]
means the task of moving data between your UI components and your
backend/domain objects, in both directions. Some Swing users are using
advanced data binding libraries like BeansBinding. BeansBinding concepts
could be adapted to Vaadin applications as well, but there are also
really handy built-in helpers into Vaadin.
There are interfaces called
https://vaadin.com/api/com/vaadin/data/Item.html[Item] and
https://vaadin.com/api/com/vaadin/data/Property.html[Property] (and utility
implementations for those), used by all Vaadin
http://vaadin.com/api/com/vaadin/data/Field.html[Field] components. You
can use those, but most often you’ll use the built in BeanItem
implementation, and typically via BeanFieldGroup helper. BeanFieldGroup
can automatically bind your entities/DTOs to the corresponding
https://vaadin.com/api/com/vaadin/ui/Field.html[Field] components.
Similarly to BeansBinding in Swing development, this saves you from
writing a huge amount of boilerplate code that basically just moves
values from UI to your domain objects and vice versa.
The BeanFieldGroup in Vaadin also supports by default
http://beanvalidation.org[Bean Validation] annotations you might have
already defined into your domain objects. The same rules can then be
used on the UI layer to automatically perform validation before throwing
your domain objects back to business layer.
If you have ever used JTable component you are probably familiar with
Swing’s interface called TableModel that is used to provide a way for
JTable to list the actual data into it. In Vaadin the similar task is
delegated to
https://vaadin.com/api/com/vaadin/data/Container.html[Container]
interface that contains Item instances. There are built in container
implementations in the framework, of which BeanItemContainer will most
probably become very familiar to you. It is a simple and efficient way
to list your entities in Vaadin Table and in various select components.
[[lazy_loading_large_data_sets]]
Lazy loading large data sets
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In your Swing apps, if you have listed big data sets into your UI, you
probably know you need to be careful what you load into your
applications memory. Also, as your data is probably shared on the server
in business applications, the network usage between your server and
client may easily become the bottleneck. Typically this is solved by
showing just the top most results of your DB query or using some sort of
“paging” when listing lots of data.
As we discussed earlier, Vaadin applications UI code has a huge aid from
being executed right next to your data. The data is often already in
your application servers memory or in a DB server that is either in the
same physical server or most likely at least connected with strong
network connection to your application server. This make data accessing
both efficient and simple.
At the same time the well optimized UI components in Vaadin only send
the essential data through the wire from server to the client. For
example in Table and ComboBox, only the visible parts of the data is
sent to the client side and this ways network usage stays low, even when
(virtually) displaying huge amounts of data.
In case you can’t (due to scalability, memory usage) load all your data
into servers memory, you’ll have to do similar tricks in Vaadin as well
or you might run out of memory with lots of concurrent users. Limiting
the result set and using paging at UI level is naturally in basic tools
for Vaadin developers as well.
But as UI components already do lazy loading between your server and
client, you can also extend the lazy loading chain all the way to the
database using “lazy loading” implementations of the
https://vaadin.com/api/com/vaadin/data/Container.html[Container API].
You can pretty easily write a totally custom version for your specific
use case, but the strongly suggested method is to use helpers like
https://vaadin.com/web/matti/blog/-/blogs/connecting-large-amounts-of-data-to-ui[LazyList]
or https://vaadin.com/addon/lazy-query-container[LazyQueryContainer]
instead. In most lazy loading cases, those are the tools that you really
should use, but in some architectures you can also consider using
https://vaadin.com/api/com/vaadin/data/util/sqlcontainer/SQLContainer.html[SqlContainer]
or https://vaadin.com/addon/vaadin-jpacontainer[JPAContainer] which do
rather optimized lazy loading automatically as well.
[[structuring_your_ui_code]]
Structuring your UI code
~~~~~~~~~~~~~~~~~~~~~~~~
If you have maintained a large Swing application, you probably know it
is possible to write messy code, event with Java and its static typing
and great IDEs. For large desktop applications, especially with large
teams and long maintained projects, you have probably applied some sort
of design patterns like MVC or MVP to structure your UI code.
The very same applies to Vaadin code as well. In large applications you
most likely want to use some sort of strict rules to structure your
code. In smaller applications it is fine to just separate logical parts
of your UI to different, possibly reusable, classes.
Thanks to similarities with Vaadin and Swing, you can apply your
existing experience on this topic directly to Vaadin. Implementing a
clean MVP pattern is a part of https://vaadin.com/training[Advanced
Vaadin course], in case you want some proven experiences on the topic.
Also, consider to use tools like http://cdi-spec.org[CDI] or
http://projects.spring.io/spring-framework/[Spring], which may help you
to implement your patterns in even more cleaner manner.
[[testing]]
Testing
~~~~~~~
One of the largest advantages of using well structured UI code is that
it often becomes easier to write tests for your UI logic. By using e.g.
MVP pattern in your code you can write unit tests for your presenter
classes.
In addition to writing unit tests to your backend and UI logic, it is
good to have full stack integration tests or automated acceptance tests.
http://arquillian.org[Arquillian] is a nice tool to write tests that run
in a e.g. Java EE container with a real DB.
Another nice helper to implement full end-to-end testing is
https://vaadin.com/add-ons/testbench[Vaadin TestBench]. It is based on
the open source Selenium project and drives real browsers and simulates
user interactions. This way you can test the whole application stack
from browser level to the database.
[[example_crud_and_its_vaadin_conversion]]
Example CRUD and its Vaadin conversion
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Lets image you have a server that stores your customer data. The
persistency and business logic is hidden behind an EJB and your Swing
based rich client reads and writes data into that via a remote EJB.
There are lots of this kind of applications or bit similar that use more
lower level communication mechanism to the database.
We will use this kind of example application and look what the different
UI implementations look like. Using this example you can hopefully get a
pretty realistic idea what converting a Swing based Applet or desktop
application into a Vaadin based web application might require and cost.
The heart of the example is the EJB that talks to the underlying RDBMS.
This part is shared by both Swing and Vaadin UI. The server used in the
example is pretty modern Apache TomEE. Although your application might
be using older technology, the concepts are most likely very similar,
even if you were using lower level RMI, CORBA or even raw DB connection.
Our example is a pretty trivial CRUD, but the business logic running in
the EJB is typically the most critical part of your application. Luckily
you can most often recycle this part of your application, as such as in
this case, or with some modernization, and just re-write the UI part.
Also at the UI part the programming model will be very familiar, so the
task will be really easy for you and your colleagues - even without any
web development experience.
In this example we will just use raw Swing and Vaadin APIs in the UI.
Some vice men in the industry have prepared for big changes in
technologies. In case you have done something like this into your UI
code the “Vaadin upgrade” might be even easier. E.g. one of our
customer, when moving from AWT to Swing, wrote a bit more generic
wrappers for their UI component and split all the UI logic to separate
controllers. This was to help transition to yet another UI framework in
the future. Today, from desktop world, you would naturally first think
JavaFX. Instead of going into JavaFX, they wanted to eliminate Java
requirement from their clients totally and go with pure browsers
technologies.
image:img/ejbswingvaadin.png[Architecture
diagram]
Architectural overview how a Swing based "thin client
application" backed by an EJB can be transferred to web era using
Vaadin. In the example application we build a both Swing and Vaadin UIs,
connecting to exactly same EJB backend.
[[application_initialization]]
Application initialization
^^^^^^^^^^^^^^^^^^^^^^^^^^
If you have been working with some larger Swing apps, you are, instead
of starting up a JFrame from your main method like in our example, most
probably using some sort of application framework as a basis. The
https://netbeans.org/features/platform/index.html[NetBeans Platform] is
an example of such. Similarly with Vaadin, it is hardly ever a good idea
to go with raw Vaadin and a servlet container.
There are couple of nice choices and in this example we are using a
standard Java EE basis and use Vaadin CDI as the “framework” that help
us to bootstrap the UI, and also in the next step to bind it to our
backend.
As a bonus, when using Vaadin CDI, you need to know even less about
Servlets and web specific stuff. In Vaadin CDI application, the entry
point to your application is the
https://vaadin.com/api/com/vaadin/ui/UI.html[UI class] that you annotate
with _@CDIUI(“”)_. The empty string means the UI’s “deployment path”,
the last part in your url that you use to access your application, which
in our example is the actual “root” of our application. If you want, you
can have multiple UI’s in your application, just map them to different
urls. The Vaadin CDI add-on will “magically” introduce the low level
Servlet and configure your UIs to be displayed via it.
If you look at
https://github.com/mstahv/ejb-swing-vaadin-crud/blob/master/server/src/main/java/org/vaadin/vaadinui/AppUI.java[the
actual UI class] in the example application, you’ll see it is
practically empty. This is because we are using a yet another extension
(our class extends ViewMenuUI from a
https://vaadin.com/addon/cdi-helpers[cdi-helpers library]) to Vaadin CDI
that creates you a basic top level application layout and view
navigation automatically. This may be just what you need, but in many
complex applications you might want to write a more domain specific
version for this this part.
The actual meat of the user interface code is written into views,
annotated with CDIView. If you introduce a following class to your
application, it will automatically automatically mapped to
http://yourapp.com/contextpaht/#!about and the cdi-helpers will
automatically register it to your applications main menu.
[source,java]
....
@CDIView("about")
public class AboutView extends VerticalLayout implements View {
@PostConstruct
void init() {
addComponent(new Label("Hello Vaadin World!"));
}
@Override
public void enter(ViewChangeListener.ViewChangeEvent viewChangeEvent) {
}
}
....
If you are not familiar with CDI or managed beans in general, you might
think why I’m doing the addComponent call in the @PostConstruct
annotated init method instead of creating a basic constructor. In this
particular case there wouldn’t be a difference, but in the next step we
will be using dependency injection to connect to our EJB. As
dependencies are not resolved yet during constructor call, it is often
simpler to do all view initialization in @PostConstruct annotated init
method instead.
The enter method is called by Vaadin each time user enters the view. It
is handy to refresh some some often changing data in it, but most often
you don’t need to do anything in it.
[[ejb_lookup]]
EJB lookup
^^^^^^^^^^
In our desktop Swing example we have an ejb-client available on our
classpath, and when the application first time needs access to the
(remote) EJB,
https://github.com/mstahv/ejb-swing-vaadin-crud/blob/master/desktop/src/main/java/org/vaadin/swingersclub/SwingApplication.java#L145-L166[it
gets resolved] using a JNDI lookup with proper parameters. This is
pretty handy actually, especially as we don’t have any proper security
control in our example.
In a real world application, if you are not using a remote EJB, client
server communication might be bit trickier, but you most likely have
some sort of remote interface you’ll somehow detect.
In Vaadin application we could use exactly the same way, but as we chose
a proper Java EE + Vaadin CDI basis for our example application, the
very same procedure can be done in much cleaner and more maintainable
manner. As our UI objects are CDI managed beans, we can simply use @EJB
or @Inject annotation to get the reference to the very same
CustomerFacade. The example below uses simple field injection, but
stricter architects might want you to use constructor or method
injection.
[source,java]
....
@Inject
CustomerService service;
....
In the further steps we’ll notice that the actual accessing our
stateless EJB is pretty much similar in both cases.
[[listing_entries_from_the_backend_to_table]]
Listing entries from the backend to Table
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In our example Swing application we are using a
https://github.com/mstahv/ejb-swing-vaadin-crud/blob/master/desktop/src/main/java/org/vaadin/swingersclub/SwingApplication.java#L58[simple
TableModel], based on AbstractTableModel, to bind our customer database
to UI table. We simply
https://github.com/mstahv/ejb-swing-vaadin-crud/blob/master/desktop/src/main/java/org/vaadin/swingersclub/SwingApplication.java#L137-L143[grab
all entities] from the backend to local List instance and create a
TableModel that serves data form the list. For larger table you’d
probably need to implement some sort of paging or just rudely limit the
amount of listed entities. The code snippet from our Swing example is
listed below. The CustomerTableModel is then passed to JTable instance.
[source,java]
....
private List<Customer> customers;
class CustomerTableModel extends AbstractTableModel {
@Override
public int getRowCount() {
return customers.size();
}
@Override
public int getColumnCount() {
return 3;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (customers == null) {
customers = getCustomerFacade().findAll();
}
Customer c = customers.get(rowIndex);
switch (columnIndex) {
case 0:
return c.getFirstName();
case 1:
return c.getLastName();
case 2:
return c.getEmail();
}
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String getColumnName(int column) {
return columnNames[column];
}
}
....
In our Vaadin application we are using technically a pretty similar
in-memory table view for the database. The example actually uses a
commonly used helper class from an add-on called Viritin, that just
accepts the list of pojos, but you gain similar result with
BeanItemContainer and raw Table component as well. Creating a basic
BeanItemContainer containing all our customers would look like this:
[source,java]
....
BeanItemContainer<Customer> bic
= new BeanItemContainer<>(Customer.class, facade.findAll());
....
The BeanItemContainer makes bean introspection to detect the available
properties and you can then limit the available columns by configuring
your https://vaadin.com/api/com/vaadin/ui/Table.html[Table] instance.
You can also get to the low level with Vaadin, like with the Swing
example, and implement a custom
https://vaadin.com/api/com/vaadin/data/Container.html[Container]
implementation that you can pass to the Table. Most often the utility
containers are what you want.
Listing the whole (database) table in a Vaadin user interface this way
is already far more efficient because the most of the data is still only
in your server. The
[Table]https://vaadin.com/api/com/vaadin/ui/Table.html) component only
sends the visible viewport the Vaadin’s “thin client” and when user
scrolls down more rows are fetched from the servers memory. You’ll save
a lots of bandwidth compared to the desktop version.
However, if we still want to make our Vaadin version better, we could
use lazy loading of data also on the server side. The MTable from the
https://vaadin.com/addon/viritin[Viritin add-on] in the following
example only needs strategies to fetch the total number of entities and
fetching entities in page manner. With Java 8 style constructs a lazy
loading “binding” to our CustomerFacade could look like this:
[source,java]
....
MTable<Customer> table = new MTable(
firstRow -> facade.findRange(firstRow, maxResults),
facade.count(),
maxResults
);
....
That scales really well both in client and in server, and uses only a
tiny bit of memory on the server side. There are lots of various lazy
loading container implementations available in the
https://vaadin.com/directory/[Vaadin Directory] and you can naturally
write one yourself as well.
[[binding_entity_to_a_form_for_editing]]
Binding entity to a form for editing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In our Swing example, we are creating an editor for our domain object in
class called CustomerForm. In it we prepare some JTextField for the
essential properties of the domain model, whose values we copy to domain
object when users clicks the save button.
[source,java]
....
JTextField firstName = new JTextField();
JTextField lastName = new JTextField();
JTextField email = new JTextField("yourname@yourdomain.com");
JButton create = new JButton("Create");
JButton update = new JButton("Update");
@Override
public void actionPerformed(ActionEvent e) {
Customer c = editedCustomer;
if (e.getSource() == create) {
c = new Customer();
}
c.setFirstName(firstName.getText());
c.setLastName(lastName.getText());
c.setEmail(email.getText());
if (e.getSource() == create) {
application.getCustomerFacade().create(c);
} else {
application.getCustomerFacade().edit(c);
}
}
....
When an existing entity is set for editing, we set the existing values
for the fields.
[source,java]
....
void editCustomer(Customer c) {
this.editedCustomer = c;
firstName.setText(c.getFirstName());
lastName.setText(c.getLastName());
email.setText(c.getEmail());
updateButtonStates();
}
....
Using this kind of low level approach is pretty similar in Vaadin as
well. Instead of JTextField you are just using TextField class from
Vaadin core and instead of getText() method you use getValue() to grab
the value from the field.
In a real life, in both Vaadin and Swing apps, you probably want to use
your life for something better than writing lots of boilerplate code for
this kind of basic forms. Vaadin comes with a really powerful tool
called BeanFieldGroup to free yourself from writing the “glue code”
between your UI fields and domain object properties. You can use either
use naming convention or a @PropertyId annotation to hint BeanFieldGroup
to do the “two way mapping” automatically. The getter-setter parts of
the above can be written using BeanFieldGroup as follows:
[source,java]
....
TextField firstName = new TextField("First name");
TextField lastName = new TextField("Last name");
TextField email = new TextField("Email");
public void setCustomer(Customer customer) {
this.customer = customer;
BeanFieldGroup<Customer> bfg
= BeanFieldGroup.bindFieldsUnbuffered(customer, this);
}
....
The BeanFieldGroup can also attach automatically constructed validators
to your fields, based on the standard http://beanvalidation.org[Bean
Validation] annotations, that you already might have on your domain
objects. Naturally, you can manually configure validators at UI layer as
well. BeanFieldGroup also provides “UI level buffering”, that might be
handy in case you happen to be using “live objects”. In typical business
apps, the backend is the right level that does the “buffering” for you.
In our Vaadin example, we are using BeanFieldGroup via an
https://github.com/mstahv/ejb-swing-vaadin-crud/blob/master/server/src/main/java/org/vaadin/vaadinui/CustomerForm.java[AbstractForm
based class]. In addition to bean binding, it provides us with basic
save, reset and delete buttons. In your own application you have the
liberty to go with low level manual binding, automatic binding using
BeanFieldGroup or with a handy helpers like the AbstractForm or your
application specific version of it. The first option has the most
control, the last has the cleanest code and is probably what you want in
most cases.
[[possible_conversion_strategy_wrappers_for_your_own_ui_framework]]
Possible conversion strategy: wrappers for your own UI framework
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Some Swing developers have created a domain specific wrappers to hide
the actual Swing API from their application code. One of our clients did
this when moving their application from AWT to Swing and then wanting to
prepare for a yet another UI library change in the future. They just
needed to make some changes to their wrappers and then create an
“adapter” for Vaadin UI.
Whether this kind of wrapper strategy really pays off probably depends
on the characteristics of the application itself. In our recent customer
case it was estimated that even though their application was huge, going
with pure Vaadin solution would have had smaller expenses. Also by
creating your own UI abstraction layer, you will lose some flexibility
and make additional development more expensive. However, the solution
has also other advantages. With this approach it is cheap to maintain
and support both modern Vaadin web client and the legacy Swing app and
still implement fixes and enhancements to only one code base.
The concept is by no means unique in the industry and SibVisions JVx
framework is based on a similar approach. UI can be implemented just
once can be deployed to both Swing and Vaadin based client applications.
[[possible-conversion-strategy-gradually-move-to-web-ui]]
Possible conversion strategy: gradually move to web UI
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Instead of rewriting the UI layer in a one big project it might be a
good idea to start moving to web era gradually. You should consider this
kind of approach especially if you have a well designed "backend" layer
and a large application. You could start with screens that are most
often needed on devices without managed software installations, like
tablets, or home computers. Then proceed the conversion on more rarely
used screens. On office computers you could keep using the existing
software, with the full feature set, during the transition period.
[[example-app-sources]]
Example app sources
^^^^^^^^^^^^^^^^^^^
The full sources for the
https://github.com/mstahv/ejb-swing-vaadin-crud[EJB CRUD example with
both Swing and Vaadin UIs] is available via GitHub.
|