In this post, you get to know the Vaadin internals that are relevant from a load-testing perspective. It is necessary to delve into these details, because they explain why you cannot simply replay a previously-recorded scenario when load testing a Vaadin app. You also need to deal with unique Vaadin traits that are not found in conventional web apps.
The internals covered here apply to web apps built with Vaadin Flow, our server-side Java framework. To keep communication between server and client secure and consistent, Flow uses a set of tokens and ids. These tokens and ids form the subject matter of this post.
Note this is the second post in our Performance testing a Vaadin application blog series. For an introduction to the subject, see Part 1.
Request and response
An HTTP request is the base unit used in web application load testing. To provide additional security measures and synchronization, the framework adds special-use attributes to the request body.
Let’s inspect a request and response payload of a simple base starter.
- Download a starter from vaadin.com/start and start it.
- Open DevTools in your browser.
- Navigate to http://localhost:8080/.
- The Network tab should contain a request similar to this:
This is the XHR (XMLHttpRequest) sent from the client side of the starter app to the server.
Select the Response tab to view the server’s response. It should look something like this:
The request contains multiple parameters, including v-uiId
, syncId
, clientId
, csrfToken
and node
. We discuss each in detail next.
csrfToken
The csrfToken
in the payload is implemented by Vaadin as a defence mechanism against a cross-site request forgery attack (CSRF). It prevents undesirable actions being performed on a user’s behalf by a malicious program on an authenticated site. The framework generates a unique token for each user. A token is created and passed to a user with the first response from a server. It is sent back with every subsequent request. The framework verifies both the validity and the existence of a value for each user request. If an issue is found with a token, the request does not proceed further on the server and an error is returned to the user.
v-uiId and node
A v-uiId
is an id that associates the server-side UI with the corresponding client-side instance. A new UI is created every time a new tab or a browser window is opened or refreshed.
A node
is a unique value of an element that associates a client-side DOM element with a server-side component. It is used in remote procedure call (RPC) requests to exclusively identify which component listener must be fired or where changes must be applied in the UI.
Synchronization tokens
To ensure messages are processed in the correct order, the framework uses two synchronization tokens internally: syncId
(server-to-client) and clientId
(client-to-server). Every time a new request is sent from a browser, the clientId
is incremented by one and added to a payload. If the expected and received values do not match on a server, a re-synchronization attempt should be issued.
The syncId
token, in contrast to the clientId
, is incremented by one with every response from a server. A client always appends the last seen syncId
value to a payload. This guarantees that requests are processed in the correct order on a server. If the received value is larger than expected, the operation is postponed until the missing messages arrive. A syncId
’s value verification can be disabled in an application to simplify the load and scalability tests that are run.
Disabling parameters
As we have seen, a Vaadin app has its own unique traits. To simplify performance testing, you can disable CSRF protection and syncId
tokens, but always. remember to reset these settings when going to production. You can find additional details on how to do this at [All Vaadin Configuration Properties](https://vaadin.com/docs/flow/advanced/tutorial-all-vaadin-properties.html)
Instead of disabling these tokens, you can also use a load-testing tool to extract these tokens from the responses. Then you can use the (dynamically) extracted values in the subsequent requests. We will show you how to do this with the JMeter and Gatling tools in later blog posts. Usually some kind of response postprocessor with a regular expression extractor is used.
Summary
Compared to other server-side frameworks, when load testing a Vaadin application you need to be aware of the following.
- A
csrfToken
is extracted from the first response from the server and passed to all subsequent requests. If a user authentication mechanism is implemented, there could be three CSRF tokens generated for a single browser session: before login, after a user is authenticated, and after logging-out. Each must be extracted and passed on for a test to function correctly. As an alternative, you can temporarily disable CSRF token protection. - Each consecutive request has a synchronization token value that is incremented by one.
- Each response is in the form of
for(;;);[response JSON]
. - An extraction postprocessor is applied to a correct response to extract required tokens and ids. Information to determine the element behind a node value is sent only once the component is attached to a UI. After this, only an integer value is used in communication between a client and server to determine an element.
- Different load testing tools have different means for extracting ids and tokens from requests. We will dive into more detail about these in later blog posts about JMeter and Gatling.