Close

The new and fully customizable In-House Training is out!

Improve your skills whenever and from wherever you want.

We are proud to present our new and fully customizable In-House Training. Benefit from a live and Vaadin Expert-led training for up to 16 attendees in a location of your choice.

What is included?

The new In-House Training can be fully customized to your own specific needs. You can freely choose each of the 30+ courses from our current training offering and tailor the training experience to the needs of yourself and your team. The training modules vary in skill level and time. Topics are ranging from basic Vaadin courses over migration courses and CDI courses to PWA based courses to improve the skills of you and your team. All interactive courses contain theory slides, hands-on coding exercises and material handouts.

Get an overview of our course offering

Where is the Value?

You and your team will learn directly from the people that have built Vaadin’s  framework, components and tools. No matter if you are kickstarting a new project or you are part of an experienced team, you will profit from the unique advantage of discussing Vaadin details within your own and specific project context directly with the trainer. With the knowledge obtained in the in-house training you’ll get to know how to integrate Vaadin with existing technology stacks and how to boost your productivity.

 

 

What does it cost?

The Vaadin In-House trainings have fixed prices per day and team size. Trainer expenses such as traveling, lodging and more are all included in the fixed price. All signups before the end of July will receive an additional 10% release discount.

For more information contact us directly

 

Client-side fail-over

Traditional clustering solutions focus on performing clustering tasks purely server-side. The browser only possesses one URL (one IP address) after all, so there is not much we can do (well, there is, but more on this later). Usually, the intent behind clustering is twofold:

  1. If one server computer crashes, the server-side setup is configured to redirect the traffic to another server computer. This is called failover.
  2. If one server computer is under heavy load, another server computer can share the load. This is called load-balancing.

Naturally, there must be some network gizmo in front of those servers - all incoming traffic is routed to a single IP by the browser after all, so there must be a special computer acting as a load balancer present there. This load balancer talks to the servers, monitors their load (and whether they are alive) and passes the traffic through to the least loaded server. Usually, this is Apache with mod_proxy or some other software-based solution; more expensive setups take advantage of hardware load balancers. The load balancer should have the following properties:

  1. The load balancer must be extremely resilient to failures - it is a so-called single point of failure after all, that is, when it crashes, it’s over and the whole cluster is unreachable. There is a technique where two computers compete for the same IP - only one succeeds and the second one just waits until the first one crashes, then takes over the IP.
  2. Different servers hold different http session objects in-memory. If the load balancer would just randomly route requests, this would cause random modifications of random sessions. Since copying a session throughout the cluster after every request is not cheap and would require cluster-wide locking, another approach is usually taken: when the user logs in, the load balancer picks a server and from now on it will route the traffic to that very server only.

The trouble with server-side clusters

Unless you are an administrator guy trained to set up a cluster of a particular web server, the cluster is not easy to set up (and most importantly - test, so that you gain confidence that the cluster actually works and performs its duties, both failover-wise and load-balancing-wise). Even the simplest options of having a group of JBosses with a special RedHat-patched Tomcat as a load-balancer (so that it can talk to JBosses and monitor them for load) takes some time to set up. Not to mention testing - often it is easier to just take the leap of faith and hope the cluster works as expected ;-)

So, for small projects clusters are often overkill; not to mention that there is this single-point-of-failure (load-balancer), unless you do an even more complex setup of having two load-balancers competing for one IP address.

What about other options?

Is it possible to get the failover/load-balancer properties some other way? How about if the browser took the role of load balancing? Obviously this is a great single-point-of-failure - when the browser crashes, it is clear to the user that she can’t browse the web until she starts the browser again. Naturally, the browser cannot possibly know the load on the servers so it can’t act as an informed load-balancer, but what about the browser doing the failover at least?

It is actually possible to bind multiple IP addresses to a single DNS record. The DNS server may then shuffle or rotate the IP list (so-called DNS round-robin), so that different browsers will try different IPs in a different order. With thousands of browsers, this works surprisingly well and the load is distributed more-or-less evenly amongst the servers. Looks great, right? Unfortunately, it isn’t. The trouble is the session. The browser is free to switch IPs often, even on every request, and if the session is not distributed amongst the computers in some way, then this approach won’t work. And distributing a session requires a server-side cluster, which we wanted to avoid. So, any other solutions?

Maybe we could implement a load-balancer inside the browser. How? JavaScript.

JavaScript-based load-balancer

The idea is simple. Publish your servers under multiple DNS names, e.g. www.service.com, www1.service.com, www2.service.com, etc. Then, once the browser visits www.service.com, along with the page it will download a special javascript code containing a list of all the servers.

Then, in case of server crash, just let that javascript code redirect to another DNS. Simple, right? Let’s discuss this a bit:

  1. This approach will force the server to always communicate with a single server, thus avoiding the necessity to distribute the session. Of course, when the server crashes, the session is lost and there is nothing we can do about it. However, clusters also tend to have trouble replicating sessions big enough (and with Vaadin it is easy to have a session as big as 200kb-1MB and more per user). It is usual that when fail-over happens, the session on the spare node may not be up-to-date, but in fact may be several minutes old, depending on the cluster configuration. This may be acceptable though; but often it is tolerable to lose the session in the event of crash.
  2. This client-side approach is so easy to test - the testing itself is almost not required. The whole load-balancer is implemented and tested by Vaadin; you only need to supply a valid set of URLs.
  3. The primary page is always downloaded off the www.service.com, thus creating a heavy load on that server. This could be remedied - if a random redirect is performed by the javascript load-balancer initially, to move away from the main server, this will distribute the load evenly.
  4. Failover is performed by the browser, which is maintained by the user. Win!
  5. This approach is not so simple to use in a regular web app, but it is so totally simple to use with Vaadin it is almost a miracle. It requires no specialized infrastructure server-side; you can deploy different web servers on different OSes if you so wish; you can deploy the application cluster-wide any way you see fit - ssh, Puppet, samba share, anything.
  6. The session does not need to be serializable; saving the session to disk can be turned off, thus improving performance.

So, how is this implemented in Vaadin? In Vaadin there is a reconnection dialog, appearing every time a connection is lost. We have just equipped the dialog with the failover code, so that in case of server crash the dialog will automatically redirect to the next server. This is exactly what the following extension does: https://vaadin.com/directory#!addon/failover-vaadin Just include the extension in your app and you are all set. Now *this* was simple, huh? You can watch the extension in action in the following Youtube video. The video shows launching of four independent Jetty instances in Docker on four different ports, 8080-8083.

There are obvious drawbacks to this solution. If the www.service.com is down, there is no way to download the JavaScript with the additional server list. So this kind of becomes single-point-of-failure. This could perhaps be remedied by employing the offline mode in HTML5, but this needs investigation. But if this was possible, the browser would only need to download the JavaScript once; since then it would be present in your browser, and will thus be able to find a live server even when the primary one is dead.

Downsides of browser-side load-balancing and failover:

  1. The JavaScript load-balancer can not possibly know whether the cause of the connectivity loss is the crash of the server or the loss of the network. It may guess - if you get a connection rejected within 1 second, then probably the server has crashed. If you have connection timeout, then the network may be down or the server may be under a heavy load. So, at some point it needs to ask the user to either reconnect to a spare server, or keep waiting. This needs investigating.
  2. DDOS attack. There is no load-balancer computer trained to divert DDOS; also DDOS may target and overload individual servers, not completely trashing them but making them really slow to respond. It might be possible to prepend the webapp with some sort of DDOS Filter though.

So, if you are willing to sacrifice the session in case of crash, this solution may be perfect for you.

Designing REST APIs

Introduction

If I had to guess, I would say that most Vaadin applications are self-contained, with the UI and the business logic packaged inside the same application archive and running inside the same Java virtual machine (VM). However, there are cases where it makes more sense to separate the UI and the backend into two separate Java applications. The applications will obviously need some way of communicating with each other and in this article, I am going to share some thoughts about doing this with REST.

In my opinion, the greatest strength but also the greatest weakness of REST is that it is essentially just HTTP. You get to decide what the messages look like, how the URLs are structured, how parameters are passed, how errors are handled, etc. On the one hand, you can build a protocol that is optimized for your particular application. On the other hand, you have to be really disciplined to keep your protocol consistent and not turn it into an incoherent mess. This is especially important if there are more than one developer working on the REST API.

Setting up the project

When setting up a project for a two-tiered application with a separate backend and frontend, the first setup that comes to mind could look something like this:

The backend and frontend have their own modules, but there is a shared module that contains the data transfer objects (DTO) that are used to transfer information over REST. I have used this model myself in several projects and have now started to think that this is actually not a good solution, especially if the DTOs are serialized to XML or JSON.

Having a shared module for the DTO unnecessarily couples the frontend and the backend to each other. This is especially troublesome if there are separate teams working on the frontend and the backend. The backend team can make changes to the DTO module without knowing how those changes will affect the frontend application and vice versa. The risk of accidentally - or intentionally - sneaking stuff into the shared module that really should not be there is also higher. Finally, this imposes limits on how you actually implement the DTOs. It might make more sense to implement the DTOs in different ways in the frontend and the backend.

Because of this, it is now my belief that if a platform agnostic remoting protocol such as REST is to be used, it is better to do a little bit of copying and keeping the backend and the frontend modules completely separate, than to have a shared library:

Choosing a message format

REST does not require you to use a particular message format. You can even use Java serialization or some other binary protocol if you want to. However, the most common alternatives are JSON and XML. Both have their pros and cons.

The advantage with using XML is that you can define all your DTOs in an XML Schema. This schema can then be used to generate Java classes wherever they are needed (both on the backend and the frontend). You also get the message format documentation “for free” and you do not need to rely on any third-party libraries or tools since Java has good built-in support for XML.

There are a few drawbacks as well. Maintaining the schema requires some work and the generated classes are the same on both the frontend and the backend. If you care about the size of the messages, JSON is more compact than XML since it does not require ending tags.

If you are designing a REST API for a frontend that is implemented in JavaScript (e.g. Polymer and Vaadin Elements), then JSON is your number one choice. This is also the alternative I would recommend if you want to code your DTOs yourself as opposed to auto-generating them. There are different libraries available for doing the actual conversion to and from JSON (personally, I prefer Jackson).

The drawback with using JSON is that you have to maintain the message format documentation and the code separately. There is a JSON Schema standard coming, but it is still a draft.

Picking HTTP methods

Picking the correct HTTP methods to use for simple CRUD operations is easy:

  • POST for Creating new entities

  • GET for Retrieving existing entities

  • PUT for Updating existing entities

  • DELETE for Deleting existing entities

However, in most non-trivial applications, you want to be able to do more than just CRUD, otherwise you are moving the business logic to the frontend or even into the heads of the users (which does not always need to be a bad thing, as long as it is intentional).

There are tens of different HTTP methods in addition to the four well-known methods mentioned before. Unfortunately, very few of them are easily usable in modern Java REST frameworks, such as JAX-RS and Spring. Therefore we are going to need to do some compromises and misuse some of the existing methods.

All HTTP methods can be classified according to two properties: safe and unsafe methods, and  idempotent and non-idempotent methods.

A safe method is guaranteed not to break anything if you call it. GET is such a method, since you should never be able to change the state of the system through a GET operation. POST, PUT and DELETE on the other hand are unsafe methods, since they can alter the state of the system.

An idempotent method is guaranteed to have the same end result regardless of how many times you call it with the same parameters (provided that nobody else has altered the state of the system between calls). GET, PUT and DELETE are idempotent methods whereas POST is not.

So what rules can we break when we need to pick a method for invoking business operations that do not fall into the CRUD category? Making a safe operation unsafe is not acceptable but vice versa is OK. This also applies to idempotency. This leads to the following rules-of-thumb:

  • If you need to perform an advanced query where the query parameters are in the request body, use a PUT. This makes an unsafe operation safe and it continues to be idempotent. You cannot use a GET here because GET requests do not have bodies.

  • If you need to perform a business operation that changes the state of the system, you have to consider the idempotency: if calling the same operation twice in a row with the exact same input parameters will have different end results or side effects, you should use a POST. Otherwise, you should use a PUT.

Designing the structure of your REST resources

Getting your resource structure right and using it consistently is very important in order to keep your REST API extendable and understandable. In one end of the spectrum, you may have a message bus inspired approach where all messages are POSTed to a single resource. The message contents dictate what to do with them.

In the other end of the spectrum, your entire data model is available as a resource tree where even individual entity properties can be addressed.

Most applications probably fall somewhere in the middle.

Versioning your API is a good idea from day one since you may end up supporting multiple versions of your REST API at the same time in the future. Instead of having the version information embedded into the HTTP request itself (for example as a header or even inside the message body), it is easier to just have it in the URL (for example /api/1.0/customers and /api/2.0/customers).

Since REST is a stateless protocol, I like to keep as much contextual information as possible in the URL path itself. Let us take an example to illustrate. In a multi-tenant system, you want to access a specific customer record (#1234) for a specific tenant (#5678). You have two approaches:

  • Infer the tenant ID from the current user: /api/1.0/customers/1234

  • Explicitly include the tenant ID in the path: /api/1.0/5678/customers/1234

I prefer the second approach since it makes the addressing absolute and the system more predictable. It also has the side effect of making it easier to support data sharing between tenants or making it possible for the same user account to access the data of multiple tenants. Obviously, you need some kind of protection mechanism that denies access to tenants that the user is not allowed to access.

However, there are also use cases where it makes more sense to infer contextual information from the current user. Take these resources for example:

  • Get the current user’s details: /api/1.0/currentUser/details

  • Change the current user’s password: /api/1.0/currentUser/changePassword

Exposing single entities and operations on them is pretty straight forward. The approach I like to use is best explained by some examples:

  • GET /api/1.0/accounts: list all accounts in the system (filtering, sorting and pagination info can be passed in as query parameters)

  • GET /api/1.0/accounts/1234: list the details of account #1234

  • PUT /api/1.0/accounts/1234: update the details of account #1234

  • POST /api/1.0/accounts: create a new account

  • DELETE /api/1.0/accounts/1234: delete account #1234

  • PUT /api/1.0/accounts/1234/lock: lock account #1234

In some cases, this is not enough. For complex views, you may want to have a specialized REST API that returns aggregated DTOs in a single call. In this case, you should start by looking over your message formats. Can you compose your aggregates out of existing DTOs or do you need to define completely new structures? In this case it is helpful to have separate DTO classes in the frontend and in the backend because you can combine them in the way that makes the most sense. An aggregate that in the backend is constructed by combining many smaller DTOs could be deserialized into one single big DTO in the frontend.

Regardless of how you choose to structure your aggregates, you need a consistent way of naming and addressing your custom endpoints. You do not want to end up in a situation where one complex view uses one type of REST API and another view uses a completely different view. Here are a few examples:

  • GET /api/1.0/accounts/summary: list a summary of the user accounts

  • GET /api/1.0/customers/1234/summary: list a summary of customer #1234

  • GET /api/1.0/agenda/day: day view of a calendar

  • GET /api/1.0/agenda/week: week view of a calendar

  • GET /api/1.0/agenda/month: month view of a calendar

  • GET /api/1.0/agenda/custom/mySpecialView: a view of a calendar that has been specialized for one particular client

  • PUT /api/1.0/globalSearch: system global search that accepts a complex query object as input

Reporting errors (and success)

Things do not always go according to plan. Errors - both caused by users and by the system itself - are inevitable and the REST API must be able to deal with them accordingly. There are two ways you can report that an error occurred:

  • Include information about whether the operation succeeded or not in the response of the request. This approach makes the most sense in a message bus like architecture where all messages are POSTed to a single REST resource. The response envelope could then include a status code and possible error message. A different HTTP status code than 200 would only be used to indicate that the server was not able to process the request at all.

  • Use the HTTP status codes and include any additional information as JSON or XML in the response body. This approach makes the most sense when you are accessing resources or performing operations by using different URLs

There are a lot of HTTP status codes and you only need to know a handful of them. The error code is enough for the client to know that something went wrong. For an improved user experience, you may want to include additional information in the body of the response that the client can parse and show to the user or store in a log.

Status code

Meaning

When to use

200

OK

Successful operations that return data (such as GETs).

201

Created

Successful operations that create new data (such as POSTs).

204

No Content

Successful operations that do not return any data (such as DELETEs).

400

Bad Request

Bad syntax of the request, unsupported message format, data validation errors, etc.

401

Unauthorized

The user is not authenticated.

403

Forbidden

The user is authenticated, but does not have permission to access the resource or perform the operation.

404

Not Found

The user tried to access a resource or perform an operation that does not exist. This code can also be used instead of 403 if we want to hide the existence of the protected resource.

409

Conflict

Optimistic or pessimistic locking errors.

500

Internal server error

All other errors.

User authentication

Finally, we are going to look at how to authenticate users. This very much depends on how you are going to implement the frontend. If your frontend includes native mobile applications or JavaScript applications that interact directly with your REST API, you need a way of authenticating the actual users of the system. In this case, my recommendation is to start by using existing authentication methods. Basic authentication or Digest authentication together with SSL/TLS are perfectly fine for this.

If your frontend also includes another system, such as a Vaadin server side application, you will need to support an authentication mechanism where the other system can perform operations on behalf of the actual users of the system. How you do this very much depends on your environment:

  • If the environment already has an authentication and authorization system in place, such as OAuth or Kerberos, it makes sense to plug into that.

  • If the backend and the frontend are trusted parties, just passing the user ID as an HTTP request header might be enough. For added security, client-side SSL authentication or API keys (a secret shared between the servers) can be used to verify the identities of both servers.

  • If the backend and the frontend are not trusted parties and you do not have an existing authentication system to rely on, you have a few alternatives (and all assume you have an encrypted channel):

    • A simple, though not very elegant solution is to keep the user’s credentials in the session and authenticate with them every time the backend is called. It works, but I am not comfortable with storing the user’s password longer than it is needed.

    • A more advanced approach is a token based system where the frontend receives a token from the backend when the user logs on. This token is then passed on with every call to the backend. The token should have an expiration date so that it cannot be misused for long in case it is compromised and it should be signed so that its integrity can be verified.

A word on service consumption

So far we have only discussed REST design and the server side of the backend. However, there are a few things worth mentioning regarding consuming REST services from a Vaadin frontend application.

The rule of thumb is quite simple: whenever you leave your Java VM to perform an operation, expect the operation to fail. Once the operation fails, you should not let it bring down the rest of your system.

In practice, the first step is to use timeouts everywhere. Use a timeout for connecting to your REST endpoint and a timeout for reading from it and keep these timeouts short and realistic.

The next step is to make sure your frontend application knows what to do when the timeouts occur. Should it automatically retry the request, fallback to a cached value or show an error message? While you are at it, remember to make sure your frontend knows how to deal with all the other error messages that your REST endpoint can return.

Finally, if you start to experience saturation, you should consider adding a circuit breaker to your frontend. Simply put, the circuit breaker will cause your requests to fail immediately if it deduces that it is not possible to process them without timing out. Once the load goes down, the circuit breaker will continue to process requests. You can try to create your own circuit breaker or rely on an existing framework such as Hystrix.

Conclusion

The freedom of protocol design that REST allows is a double-edged sword. On the one hand, it makes it possible to create an API that is optimized for your specific application. On the other hand, it is very easy to turn the API into an inconsistent mess.

When you start to design your API, you need to consider the following things:

  1. What message format are you going to use (JSON, XML, something else)?

  2. What will the REST resources be and how will they be addressed?

  3. What HTTP methods will you use and for what purposes?

  4. What error codes will you use and when?

  5. How will the system be secured?

Once you know all this, you can get to work on the API. It should be possible to implement 90% of your API like this. For the remaining 10% it is OK to break your own rules, but in that case you have to keep the anomalies isolated so that they do not become your new standard.

Designing a REST API is an iterative process where you may need to go back and revisit some parts as you gain more knowledge of the system you are building. However, once a REST API goes live, you have limited possibilities to change it without releasing a new version of the API.