- A hitchhiker’s guide to convert a Swing app to modern web app
- Intro
- Welcome to the “wonderful” world of web apps
- Architectural differences you should notice
- Basic component usage
- Event handling and Event dispatching thread
- Application bootstrap
- Laying out components
- Visual view composition
- Binding data to components
- Structuring your UI code
- Testing
- Example CRUD and its Vaadin conversion
A hitchhiker’s guide to convert a Swing app to modern web app
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 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 “wonderful” world of web apps
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
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
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, VaadinSession, HttpSession or e.g. @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
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. GWT is a great library for this kind of applications.
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.
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:
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 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
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
A Vaadin application is basically a 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 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:
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. Java EE environment with Vaadin CDI add-on or 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”.
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) {
}
}
Screenshot of the hello world view
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
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 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 Sampler application.
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 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
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.
Vaadin Eclipse plugin comes with 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 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 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 Item and Property (and utility implementations for those), used by all Vaadin 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 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 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 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
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 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 “LazyList” or LazyQueryContainer instead.
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 Advanced Vaadin course, in case you want some proven experiences on the topic. Also, consider to use tools like CDI or Spring, which may help you to implement your patterns in even more cleaner manner.
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. 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 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
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.
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
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 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 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 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 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.
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
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, 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.
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
In our example Swing application we are using a simple TableModel, based on AbstractTableModel, to bind our customer database to UI table. We simply 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.
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:
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 Table instance. You can also get to the low level with Vaadin, like with the Swing example, and implement a custom 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 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:
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 Vaadin Directory and you can naturally write one yourself as well.
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.
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.
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:
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 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 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
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
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
The full sources for the EJB CRUD example with both Swing and Vaadin UIs is available via GitHub.