vaadin/flow

Vaadin 20: Couldn't find the definition of the element with tag 'collapsible-vaadin-split-layout'

Closed this issue · 7 comments

Description of the bug / feature

I just upgraded a Vaadin Flow Project from 19.0.8 to 20.0.1 and now I get the following error, when accessing a view, which contains the CollapsibleSplitLayout:

java.lang.IllegalStateException: Couldn't find the definition of the element with tag 'collapsible-vaadin-split-layout' in any template file declared using '@jsmodule' annotations. Check the availability of the template files in your WAR file or provide alternative implementation of the method getTemplateContent() which should return an element representing the content of the template file

I checked and the files are there inside node_modules/@vaadin/flow-frontend/src.
I already tried to solve the issue using the help from the chat as I was expecting a problem with our project.
What we found so far is that the issue is not related to the used add-on (in my case CollapsibleSplitLayout) and can be reproduced using a vaadin starter project.
It also seems to be an issue that only occurs on Windows the same project works fine on a Mac

Minimal reproducible example

  1. Create a new starter on https://start.vaadin.com/app/
  2. Add the following dependency to the pom.xml:
        <dependency>
            <groupId>org.vaadin.tarek</groupId>
            <artifactId>collapsible-splitlayout</artifactId>
            <version>1.0.2</version>
        </dependency>
  1. Create a view with following code:
@Route(value = "Test")
@RouteAlias(value = "")
@PageTitle("Test")
public class TestView extends Div {

    public TestView() {
        CollapsibleSplitLayout cs = new CollapsibleSplitLayout();
        cs.setSizeFull();
        cs.addToPrimary(new Span("Primary"));
        cs.addToSecondary(new Span("Secondary"));
        add(cs);
    }
}
  1. Start the application and open the view.

Expected behavior

The view should show a CollapsibleSplitLayout.

Actual behavior

Following error is shown instead:

There was an exception while trying to navigate to '' with the exception message 'Error creating bean with name 'com.example.application.views.test.TestView': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.application.views.test.TestView]: Constructor threw exception; nested exception is java.lang.IllegalStateException: Couldn't find the definition of the element with tag 'collapsible-vaadin-split-layout' in any template file declared using '@jsmodule' annotations. Check the availability of the template files in your WAR file or provide alternative implementation of the method getTemplateContent() which should return an element representing the content of the template file'

Versions:

- Vaadin / Flow version: 20.0.1
- Java version: 11.0.9
- OS version: Windows 10 version 2004
- IDE (if applicable): IntelliJ IDEA 2021.1.2

I've had similar problems with other addons aswell with vaadin 20 when I tried to migrate. Seems like in the resolver there is an additional prefix "META-INF/resources" in the dependency HashMap, which causes the JSModule path not being resolved properly. I just wonder if this is a bug or an undocumented change on where to put js files.

I also have a similar problem. For me it was with https://github.com/appreciated/apexcharts-flow. Worked around it with a custom ResourceProvider adjusting the path:

override fun getApplicationResource(path: String): URL {
    val realPath = if(path.contains("appreciated")) {
        "./META-INF/resources/frontend${path.removePrefix(".")}"
    }  else {
        path
    }
    ...

Based on @F43nd1r comment, this is my java workaround for now:

public class ViewListenerWorkaround implements VaadinServiceInitListener {
    @Override
    public void serviceInit(ServiceInitEvent initEvent) {
        // https://github.com/vaadin/flow/issues/11220
        initEvent.addDependencyFilter((dependencyList, context) ->
                dependencyList.stream().map(dependency -> {
                    if (dependency.getUrl().matches("^\\./.*\\.js$")) {
                        return new Dependency(dependency.getType(), dependency.getUrl().replaceAll("^\\./", ""), dependency.getLoadMode());
                    }
                    return dependency;
                }).collect(Collectors.toList())
        );
    }
}

Tried to reproduce using the instructions. Application starts normally and shows a collapsible split layout.
Code here https://github.com/Artur-/test-11220

What is missing?

Tested on macOS. Is this a Windows problem?

@Artur- for me it only shows up in production mode, on linux

@Artur- yes, it seems to be a windows problem.

For some reason the expected path node_modules/@vaadin/flow-frontend/ is generated as ../target/flow-frontend/
As the source can be found from the stats.json from webpack "name": "../target/flow-frontend/src/collapsible-vaadin-split-layout.js",
What changed this for 20 should be investigated.