404 for js files when using spring boot with vaadin

I have a problem when using spring security in a vaadin project with spring-boot. So I am using PdfViewer Addon to display PDF files. But I am getting the following error:

error:"Not Found"
message:"No message available"
path:"/APP/PUBLISHED/pdf.worker.js"
status:404

      

and my spring security config looks like this:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .headers()
                .defaultsDisabled()
                .frameOptions().sameOrigin().and()
                .csrf().disable() // Use Vaadin CSRF protection
                .authorizeRequests().antMatchers("/").permitAll()
                .antMatchers("/vaadinServlet/HEARTBEAT/**").permitAll()
                .antMatchers("/vaadinServlet/UIDL/**").permitAll()
                .antMatchers("/vaadinServlet/APP/PUBLISHED/**").permitAll()
                .antMatchers("login?debug").permitAll()
                .antMatchers("/#!pwdreset/*").permitAll()
                .antMatchers("/pwdreset/*").permitAll()
                .and()
                .authorizeRequests()
                .and()
                .formLogin().loginPage("/#!login").permitAll()
                .and()
                .logout().logoutUrl("/#!login?logout").logoutSuccessUrl("/").permitAll().and()
                .sessionManagement().sessionFixation().newSession();

    }

@Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**", "/VAADIN/**");
    }

      

So, while checking the downloaded files in Chrome, I see the / vaadinServlet / APP / PUBLISHED / folder , and there are all the required files.

Using Addon without spring Security works great, so any idea?


Update

It looks like it has nothing to do with spring security because I get similar behavior when testing the Addon on a new simple project. Seems to be a problem with spring boot.

To reproduce this issue you need ( complete project to download ):

  • basic spring boot + vaadin app skeleton
  • simple PDF and under /webapp/files

  • add-on PdfViewer in your computer and widgets compiled
  • below simple user interface
@Theme("mytheme")
@SpringUI
@Widgetset("org.test.AppWidgetSet")
public class MyUI extends UI {
    @Override
    protected void init(VaadinRequest vaadinRequest) {
        final VerticalLayout layout = new VerticalLayout();
        String basepath = VaadinService.getCurrent().getBaseDirectory().getAbsolutePath();
        File file = new File(basepath.concat("/files/test.pdf"));
        if (file.exists()) {
            PdfViewer pdfViewer = new PdfViewer(file);
            Label info = new Label("File was found!");
            layout.addComponents(info, pdfViewer);
        } else {
            Label info = new Label("no file found!");
            layout.addComponent(info);
        }
        setContent(layout);
    }
}

      

  • Open chrome and developer tools tabbed Network

    , select an app and you will see one prompt for pdf.worker.js

    .
+3


source to share


1 answer


TL; DR; version:

The second request is fired pdf.js

to download pdf.worker.js

, but it doesn't match the path /vaadinServlet/APP/PUBLISHED/pdf.worker.js

that is handled by the auto-configured one VaadinServlet

, it's easy /APP/PUBLISHED/pdf.worker.js

.

The simplest solution I could come up with is a controller that redirects the request VaadinServlet

:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class PdfJsRedirectController {
    private static final String WORKER_JS_INCORRECT_PATH = "/APP/PUBLISHED/pdf.worker.js";
    private static final String WORKER_JS_CORRECT_FORWARD_PATH = "forward:/vaadinServlet/APP/PUBLISHED/pdf.worker.js";

    @RequestMapping(value = WORKER_JS_INCORRECT_PATH)
    public String forwardWorkerJsRequestToVaadin() {
        return WORKER_JS_CORRECT_FORWARD_PATH;
    }
}

      


Detailed version:

So, I spent some time debugging and it turned out to be a combination of bad configurations:

  • spring listen for dispatcher servlets
  • vaadin spring listening servlets
  • a pdf.js bugfix / woraround

What happens is spring logs requests DispatcherServlet

to serve /*

. and Vaadin registers a VaadinSpringServlet

for paths /vaadinServlet/*

and /VAADIN

:



ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
ServletRegistrationBean  : Mapping servlet: 'springVaadinServlet' to [/vaadinServlet/*, /VAADIN/*]

      

To coexist with the dispatcher servlet and be able to serve requests to "/ *" as well, Vaadin also registers a forwarder for paths UI

. For example, requests for /MyUI

will be redirected to /vaadinServlet/MyUI

(see VaadinServletConfiguration

sources
for details ).

Everything is working fine so far and you shouldn't have any problems. Just like you said looking at the hrome dev-tools all the files js

are there, so what's wrong? If you look at the requests made while accessing your application, you will notice that there are actually 2 requests for pdf.worker.js

- the first one successful, and the one that gives you a 404:

pdf.worker.js requests

The column Initiator

for the call that fails, in fact pdf.js:2344

, and if you set a breakpoint, you can see that workerSrc=/APP/PUBLISHED/pdf.worker.js

, the value that is defined in pl.pdfviewer.client.ui.PdfViewer.java

. You may have to scroll horizontally a little to see the code, so I formatted it below:

public native void loadResourcePdf(String fileName, VPdfViewer instance)/*-{
    var pdfviewer = instance.@pl.pdfviewer.client.ui.VPdfViewer::jsObject;
    pdfviewer.work = false;
    if ((pdfviewer.fileName == null || pdfviewer.fileName != fileName) && fileName != null) {
        $wnd.PDFJS.disableStream = true;
======> $wnd.PDFJS.workerSrc = 'APP/PUBLISHED/pdf.worker.js';
        $wnd.PDFJS.getDocument(fileName).then(function (pdf) {
            pdfviewer.pdfFile = pdf;
            pdfviewer.fileName = fileName;
            pdfviewer.pageCount = pdf.numPages;
            if (pdfviewer.pageNumber == 0 && pdf.numPages > 0) {
                pdfviewer.pageNumber = 1;
            }
            pdfviewer.showPdfPage(pdfviewer.pageNumber);
        });
    }

}-*/;

      

js debug

In a normal environment Vaadin /APP/PUBLISHED/pdf.worker.js

will work out of the box, but now we have changed a little so we need some tweaks. At the bottom, we can take a similar approach to what Vaadin's auto-setup does and redirect the request /APP/PUBLISHED/pdf.worker.js

to /vaadinServlet/APP/PUBLISHED/pdf.worker.js

and finally overcome this issue. For brevity, the redirect controller can be seen at the beginning of this post.

working pdf

+1


source







All Articles