Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Application run with Spring Boot Maven plugin does not discover all routes #266

Open
denis-anisimov opened this issue Apr 18, 2018 · 0 comments

Comments

@denis-anisimov
Copy link

@heruan commented on Thu Mar 01 2018

Running a Flow application with Spring Boot Maven plugin does not discover @Route components in dependencies.

In this app: https://github.com/heruan/flow-spring-multimodule there are two modules:

  • flow-spring-app: with a @Route("") component
  • flow-spring-module: with a @Route("module") component

Running flow-spring-app with mvn spring-boot:run opening http://localhost:8080/module returns:

Could not navigate to 'module'. Reason: Couldn't find route for 'module'

But other Spring beans from the module (e.g. ModuleService) are discovered correctly.

Note that if the app is deployed in WildFly, all works as expected. I'm facing this with integration tests, where a component I'm testing has a new RouterLink("Foo", ComponentInOtherModule.class) which fails since the target component isn't discovered during the test (run with the spring-boot-maven-plugin).


@Legioth commented on Mon Mar 05 2018

The reason for this is that @Route types are generally picked up using the servlet container's own classpath scanning mechanism (javax.servlet.ServletContainerInitializer).

The embedded servlet container used by Spring Boot has this functionality explicitly disabled for performance reasons, so in those cases we have to fall back to using Spring's own classpath scanning mechanism that has different logic for determining where to look.

One potential way around this might be to consistently use the Spring mechanism even in cases when the servlet container's own scanning has already been triggered.


@heruan commented on Fri Mar 09 2018

The embedded servlet container used by Spring Boot has this functionality explicitly disabled for performance reasons

Is it possible to re-enable it somehow, as a workaround until a proper solution?


@heruan commented on Fri Mar 09 2018

This is working for me as a workaround:

@Component
public class SpringRouteRegistryInitializer extends RouteRegistryInitializer
        implements ServletContextInitializer {

    private static final String PACKAGE = "it.axians";

    @Override
    public void onStartup(ServletContext servletContext)
            throws ServletException {
        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(
                false);
        provider.addIncludeFilter(new AnnotationTypeFilter(Route.class));
        provider.addIncludeFilter(new AnnotationTypeFilter(RouteAlias.class));
        Set<Class<?>> classSet = provider.findCandidateComponents(PACKAGE)
                .stream().map(BeanDefinition::getBeanClassName)
                .map(className -> {
                    try {
                        return Class.forName(className);
                    } catch (ClassNotFoundException e) {
                        return null;
                    }
                }).filter(Objects::nonNull).collect(Collectors.toSet());
        super.onStartup(classSet, servletContext);
    }

}

@Legioth commented on Tue Mar 13 2018

Great that you found a workaround!

Is it possible to re-enable it somehow, as a workaround until a proper solution?

I don't think so. See spring-projects/spring-boot#321 for more details.


@pleku commented on Tue Mar 13 2018

Since there is a workaround for this bug - I'm deprioritizing this issue for now in favor of fixing other bugs.

Let us know if the workaround is not an option anymore.


@heruan commented on Tue Mar 13 2018

Totally agree, no problem with that! BTW it would be cool to have visibility of issue priorities, e.g. with labels or milestones.


@denis-anisimov commented on Thu Mar 22 2018

In reality we have logic which implements almost the same workaround already for the Spring Boot application.

It doesn't work in your case by the reason of different package names.
Your application package name is to.lova.flow.spring.app. And this package (the application package) is used to discover routes in our "workaround" implementation.
But your maven module has routes in the package to.lova.flow.spring.module. So the routes are not discovered there.

The workaround in your case (without writing any additional code) would be to move your application class into to.lova.flow.spring app or any its parent package.

But we should provide a way to specify packages where routes should be discovered (the same way as @EnableJpaRepositories annotation does).

There is even "TODO" methods in the code which I made explicitly keeping in mind that we will need to adjust package name retrieval for those cases. But I had no time to fix this.


@heruan commented on Thu Mar 22 2018

Great, thank you @denis-anisimov! I would suggest @RouteScan in the line of Spring’s @EntityScan or @ComponentScan.


@denis-anisimov commented on Fri Mar 23 2018

@RouteScan would have been good if it had been only routes issue.
We have a number of types that are scanned at startup and for each and every of them we have this workaround implemented. Technically each such scanning should have its own annotation but I think it's overhead to introduce an additional annotation for every such case.
So I've added @VaadinScan annotation which covers all such cases ( routes, custom elements, error pages, some validations).
The annotation name may be changed if nobody likes it. But at least the functionality is implemented in the provided PR.

I actually noticed that you may use @SpringBootApplicaiton annotation with packages to scan as a value (so it's the default base packages). So it may already work without any additional annotation.

Still need to update tutorials.


@heruan commented on Fri Mar 23 2018

We have a number of types that are scanned at startup […]

Then I'd see more fit to specify the packages to scan via a String[] attribute in @EnableVaadin instead of a @VaadinScan annotation.

I actually noticed that you may use @SpringBootApplicaiton annotation with packages to scan as a value (so it's the default base packages). So it may already work without any additional annotation.

It doesn't, unfortunately 😕


@denis-anisimov commented on Fri Mar 23 2018

Then I'd see more fit to specify the packages to scan via a String[] attribute in @EnableVaadin instead of a @VaadinScan annotation.

Actually, it's a good idea.


@denis-anisimov commented on Fri Mar 23 2018

It doesn't, unfortunately 😕

True, @SpringBootApplicaiton annotation doesn't set default autoconfiguration package.
I will add the logic which handles packages from @SpringBootApplicaiton annotation also.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant