Embedding Vaadin spring-boot application into HTML

Hi forum,

currently I’m having a hard time embedding a Vaadin application into an HTML page.

What do I use:

  • Vaadin 7.6.6
  • vaadin-spring
  • spring-boot 1.3.5.RELEASE

To enable CORS in combination with spring-boot, I adapted Sami’s Blog entry https://vaadin.com/blog/-/blogs/using-cors-with-vaadin and created the following custom CORS servlet:

[code]
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;

import com.vaadin.spring.server.SpringVaadinServlet;

/**

  • This custom {@link SpringVaadinServlet} enables CORS in combination with
  • Spring.
  • @author Christoph Guse

*/
public class CORSServlet extends SpringVaadinServlet {

/**
 *
 */
private static final long serialVersionUID = -2482991123719720492L;

/**
 * Override to handle the CORS requests.
 */
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    // Origin is needed for all CORS requests
    String origin = request.getHeader("Origin");
    if (origin != null && isAllowedRequestOrigin(origin)) {

        // Handle a preflight "option" requests
        if ("options".equalsIgnoreCase(request.getMethod())) {
            response.addHeader("Access-Control-Allow-Origin", origin);
            response.setHeader("Allow", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS");

            // allow the requested method
            String method = request.getHeader("Access-Control-Request-Method");
            response.addHeader("Access-Control-Allow-Methods", method);

            // allow the requested headers
            String headers = request.getHeader("Access-Control-Request-Headers");
            response.addHeader("Access-Control-Allow-Headers", headers);

            response.addHeader("Access-Control-Allow-Credentials", "true");
            response.setContentType("text/plain");
            response.setCharacterEncoding("utf-8");
            response.getWriter().flush();
            return;
        } // Handle UIDL post requests
        else if ("post".equalsIgnoreCase(request.getMethod())) {
            response.addHeader("Access-Control-Allow-Origin", origin);
            response.addHeader("Access-Control-Allow-Credentials", "true");
            super.service(request, response);
            return;
        }
    }

    // All the other requests nothing to do with CORS
    super.service(request, response);

}

/**
 * Check that the page Origin header is allowed.
 */
private boolean isAllowedRequestOrigin(String origin) {
    // TODO: Remember to limit the origins.
    return origin.matches(".*");
}

}
[/code]Additionally I found some documentation about spring-boot and CORS, so I added this Spring configuration:

[code]
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import CORSServlet;

/**

  • @author Christoph Guse

*/
@Configuration
public class AuthAppVaadinApplicationConfiguration {

@Bean
public WebMvcConfigurer corsConfigurer(){
    return new WebMvcConfigurerAdapter() {
        
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**").allowedOrigins(".*");
        }
        
    };
}

@Bean(name="vaadinServlet")
public CORSServlet corsServlet(){
    
    return new CORSServlet();
    
}

}
[/code]My HTML looks like this:

[code]

<?xml version="1.0" encoding="UTF-8" ?> Embedding a Vaadin Application in HTML Page

Embedding a Vaadin UI

This is a static web page that contains an embedded Vaadin application. It's here:

You have to enable javascript in your browser to
use an application built with Vaadin.

Please view the page source to see how embedding works.

[/code]My problem is the application is initally loaded, but several icons are missing and if I trigger an action in the appliction, i.e. open a dropbox, then the application is not able to do the connect to the spring-boot application. Error messages look like this: [code] XMLHttpRequest cannot load http://vaadin.poc:8090/UIDL/?v-uiId=0. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 403. [/code]Is there anybody out there who managed to embed a Vaadin spring-boot application into another HTML application?

Any hint is highly appreciated.
Christoph

Hi all,

unfortunately there wasn’t any suggested so far.
For a better discussion base I created a demo application which shows the problem. The sourcecode can be found in GitHub
https://github.com/flexguse/vaadin-html-embedding
.

It would be great if somebody could help me embedding a Vaadin application into HTML.

Cheers,
Christoph

Hi,

Hey! first of all, excellent way of asking on forums! I reproduced the problem and fixed it by adding the following script into the
HEAD
section of your HTML file:

[code]

... [/code]I created a pull request with the fix to your repository: [url] https://github.com/flexguse/vaadin-html-embedding/pull/1 [/url]

Hi Alejandro,

thanks a lot, you made my day! I’ve already merged your pull request and the application start working.

One thing I notices: the fonts are not loaded correctly (I tried the current Chrome and Firefox in Windows), I get errors like
downloadable font: download failed (font-family: “Open Sans” style:normal weight:normal stretch:normal src index:1): bad URI or cross-site access not allowed source: http://localhost:8080/VAADIN/themes/valo/fonts/open-sans/OpenSans-Regular-webfont.woff

Unfortunately the FontAwesome icons are located in such a font. Do you have an idea how to solve that?

Cheers,
Christoph

Hi Alejandro,

I found a working solution by replacing the CORSServlet by the
filter based CORS
support provided by spring-boot. The example is now working like a charm, the fonts are loaded properly.

I updated the example project and it’s documentation.

Thanks a lot again for giving me the missed piece of JavaScript!

Cheers,
Christoph

I don’t use Spring and I have this problem.
Anybody know how resolve this?

I could take a look at the problem if you provide a minimal working project to reproduce the issue.

Hi Guys, sorry for posting on existing thread. My problem is also same as this thread.
I am trying to embed Vaadin Spring Boot application in HTML page. However i am able to embed the application but none of the controls are working. when i try to click on any controls like combo box or options group,it is giving me message like “Server connection lost trying to reconnect” with spinning wheel.

I tried all the above approaches like vaadin Servlet and filter based CORS. But none of them is working.

I really apprieciate your immediate help.

Can you share both server and client logs?

Hi I am trying to embed into HTML page a aplication based in https://vaadin.com/docs/v8/bakeryfw8/overview.html , after I clone the https://github.com/flexguse/vaadin-html-embedding and check that was working , I made the following changes in my project:

in the file ApplicationConfiguration , I add the @bean org.springframework.boot.web.servlet.FilterRegistrationBean;
instead of org.springframework.boot.context.embedded.FilterRegistrationBean;
because I am using SpringBoot >1.5.7.RELEASE instead of 1.3.6.RELEASE

[code]
import org.springframework.boot.web.servlet.FilterRegistrationBean;
@Configuration
public class ApplicationConfiguration {

/**
 * The password encoder to use when encrypting passwords.
 */
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

@Bean
SecuredViewAccessControl securedViewAccessControl()
{
    return new SecuredViewAccessControl();
}
@Bean
public FilterRegistrationBean corsFilter() {

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0);
    return bean;

}

}
[/code]then I use the following HTML

[code]
<!doctype html>

html, body { height: 100%; margin: 0; }
You have to enable javascript in your browser to use an application built with Vaadin.
//<![CDATA[ if (!window.vaadin) alert("Failed to load the bootstrap javascript: http://localhost:8080/AppBakeryOven/VAADIN/vaadinBootstrap.js?v=7.6.7"); if (typeof window.__gwtStatsEvent != 'function') { vaadin.gwtStatsEvents = []; window.__gwtStatsEvent = function(event) { vaadin.gwtStatsEvents.push(event); return true; }; } vaadin.initApplication("AppBakeryOven-1295176625",{ "theme": "apptheme", "versionInfo": { "vaadinVersion": "8.1.4", "atmosphereVersion": "2.4.11.vaadin2" }, "widgetset": "wse5d4638ee018f472adfb5cee31233528", "widgetsetReady": true, "comErrMsg": { "caption": "Communication problem", "message": "Take note of any unsaved data, and click here or press ESC to continue.", "url": null }, "authErrMsg": { "caption": "Authentication problem", "message": "Take note of any unsaved data, and click here or press ESC to continue.", "url": null }, "sessExpMsg": { "caption": "Session Expired", "message": "Take note of any unsaved data, and click here or press ESC key to continue.", "url": null }, "vaadinDir" : "http://localhost:8080/AppBakeryOven/VAADIN/", "debug" : true, "standalone" : true, "heartbeatInterval" : 300, "serviceUrl" : "http://localhost:8080/AppBakeryOven/vaadinServlet/", "browserDetailsUrl" : "http://localhost:8080/AppBakeryOven" });
    //]]>
</script>
[/code]but the problem is when I run it I get a white screen , and If I check in browser console I get he following errors:

[Error] Cross-origin redirection to http://localhost:8080/AppBakeryOven/?v-1508542655822 denied by Cross-Origin Resource Sharing policy: Origin null is not allowed by Access-Control-Allow-Origin. [Error] Failed to load resource: Cross-origin redirection to http://localhost:8080/AppBakeryOven/?v-1508542655822 denied by Cross-Origin Resource Sharing policy: Origin null is not allowed by Access-Control-Allow-Origin. (AppBakeryOven, line 0) [Error] XMLHttpRequest cannot load http://localhost:8080/AppBakeryOven?v-1508542655822 due to access control checks. [Error] TypeError: null is not an object (evaluating 'appDiv.innerHTML = text') onreadystatechange (vaadinBootstrap.js:187) How can I embed in HTML page the APP that is running over Tomcat , instead of standalone SpringBot , by example the “Bakery App Starter for FW8 and Spring/JavaEE”?

@Cesar, you have to enable
Cross-Origin Resource Sharing (CORS)
. Here’ an example using
CORS Filter
:
https://github.com/alejandro-du/embedded-ui-example/blob/master/embedded2/src/main/java/org/test/WebConfig.java

Alejandro Duarte:
Hi,

Hey! first of all, excellent way of asking on forums! I reproduced the problem and fixed it by adding the following script into the HEAD section of your HTML file:

<head>
...
<script>
XMLHttpRequest.prototype._originalSend = XMLHttpRequest.prototype.send;
var sendWithCredentials = function(data) {
  this.withCredentials = true;
  this._originalSend(data);
};
XMLHttpRequest.prototype.send = sendWithCredentials;
</script>
</head>

I created a pull request with the fix to your repository: https://github.com/flexguse/vaadin-html-embedding/pull/1

Hi Alejandro Duarte,
I am using vaadin8 and in side my vaadin application I have one iframe where i am showing my other html application so i want to call my vaadin application javascript function from html project.

I am creating The javascript function like
Page.getCurrent().getJavaScript().addFunction(“function”, this::function);

But inside html project i have also some button events and when the event fires i called “parent.function();” and it gives cross origin error

Imran Momin, you probably have to enable CORS.

I did some code to enable but it’s not working
Could you please share some code ?

Here’ an example using [CORS Filter]
(http://software.dzhuvinov.com/cors-filter-configuration.html): https://github.com/alejandro-du/embedded-ui-example/blob/master/embedded2/src/main/java/org/test/WebConfig.java

I already tried with that code and I have a vaadin-spring-boot application.

If you get cross-origin errors, that’s very likely the issue. At least, I cannot think of anything else, I suggest you investigate a bit more your code and servers configurations and try to find if CORS is really enabled (it seems, it’s not).

In you case, your both application is a vaadin but in my case one is vaadin and other is simple html and javascript

You still need to enable CORS in the application you are embedding (I guess the simple HTML/JavaScript one).