Can you use Vaadin if your site doesn't run on a Java server? Many websites operate on platforms that might not support Java natively. You might have a blog, a static site, or a platform-managed service, but you may still want to leverage Vaadin's powerful features for your web application.
You can host your Vaadin application on a separate Java server or a modern cloud service like AWS, Azure, Google Cloud Platform, or Fly.io. Then, embed your Vaadin application into an HTML element on the page of your primary domain, whether that is made with WordPress, Wix, or Jekyll, or even if it resides on a different domain.
You might already be familiar with Vaadin WebComponentExporter, which allows you to publish Vaadin views or whole applications as simple HTML tags and web components and embed them in your HTML like: <newsletter-subscription></newsletter-subscription>
So far, this is pretty straightforward, but when you deploy your applications in the cloud and different domains, this is what you might see in your browser console:
This is where you need some extra configuration. The same-origin policy in web application security prevents HTTP requests made via XMLHttpRequest from being sent to different domains. This policy is strict and based on the scheme, hostname, and port number.
So, how can we integrate Vaadin applications into any web page? By enabling CORS, we can securely embed them across different domains. Let's take a look at this in more detail.
What is Cross-Origin Resource Sharing (CORS)?
Cross-Origin Resource Sharing (CORS) is a W3C specification that enables cross-domain communication from the browser. This is needed for Vaadin applications hosted on different servers from where they are embedded.
To set up CORS for your Vaadin app, it's helpful to understand the Vaadin client-server communication flow. The diagrams below illustrate the normal setup and the CORS multi-domain setup.
There are two types of requests from the browser to the server: the initial request (1) that defines the origin domain and event requests (3) for the Vaadin application. Resource requests (2) are not an issue as they do not involve XMLHttpRequest logic.
For a multi-domain setup with CORS, modify the HTTP headers for type 3 requests. This can be achieved by implementing the @WebFilter
class service method where these requests are handled.
Server-side headers
Here is a solution for adding CORS in your Vaadin app running Spring Boot.
The CORS approach involves two types of requests: the preflight OPTIONS request and the actual payload GET and POST requests. This method effectively allows the app to communicate with a domain different from where it is displayed.
@WebFilter(filterName = "Vaadin CORS Filter", asyncSupported = true, urlPatterns = "/*")
public class VaadinCorsFilter extends HttpFilter {
/* ... */
@Override
public void doFilter(HttpServletRequest httpRequest, HttpServletResponse httpResponse, FilterChain filterChain) throws IOException, ServletException {
String origin = httpRequest.getHeader("Origin");
// Allowed origin check
if (isOriginAllowed(origin)) {
httpResponse.setHeader("Access-Control-Allow-Origin", origin);
httpResponse.addHeader("Access-Control-Allow-Credentials", "true");
}
// Preflight response headers
if ("options".equalsIgnoreCase(httpRequest.getMethod())) {
httpResponse.addHeader("Access-Control-Allow-Methods", "GET, POST");
httpResponse.addHeader("Access-Control-Allow-Headers", "content-type");
httpResponse.getWriter().flush();
return;
}
filterChain.doFilter(httpRequest, httpResponse);
}
}
Find the full source code here.
And that's it; now you can run your Vaadin applications anywhere, right? Not quite.
Secure session cookie
In 2024, browser third-party cookie restrictions will get tighter, and to keep Vaadin applications running, you need to configure your session cookies correctly. In Java Servlet-based applications, like Vaadin applications, there is typically a JSESSIONID
set for session tracking.
Effectively this means you need to add two extra attributes to the session cookie to make it work: SameSite=None and Secure. As part of the 2024 third-party cookie phaseout in Chrome, there is also a new restriction to add the Partitioned
attribute to make embedding applications possible. So in total your HTTP Set-Cookie header should look something like this:
Set-Cookie: JSESSIONID=CAD...81198C; Path=/; Secure; HttpOnly; SameSite=None; Partitioned
Here is a code snippet for how to upgrade your session cookie in Spring Boot's Tomcat environment.
Embedding the Vaadin application on an HTML page
Let’s move to the easy part: the client-side code needed to add a remote Vaadin application. Here is how you
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Load the Vaadin web component -->
<script type="module" src="https://your.app.domain/web-component/newsletter-subscription.js"></script>
</head>
<body>
<!-- Use the web component on your page -->
<newsletter-subscription></newsletter-subscription>
</body>
</html>
Now you are ready to go. Install your Vaadin application on a Java server as usual, publish it using WebComponentExporter, configure HTTP headers as described here, and add it to any site you choose.
Take it into action
That's all, really. For a real-world example, I used the code above to embed a newsletter subscription form running at vaadin-cors-sample.fly.dev into a separate page, samie.github.io/vaadin-cors-sample.
For further discussion, head to the Vaadin forum. See you there!