You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

VaadinTutorialForSwingDevelopers.asciidoc 43KB

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