123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952 |
- ---
- 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
- <<ConnectingLargeAmountsOfDdataToUI#connecting-large-amounts-of-data-to-ui,"LazyList">> or https://vaadin.com/addon/lazy-query-container[LazyQueryContainer]
- instead.
-
- [[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.
|