flow icon indicating copy to clipboard operation
flow copied to clipboard

Swagger UI shows a blank page

Open tarekoraby opened this issue 3 years ago • 12 comments

Description of the bug / feature

In a Vaadin 18 + Spring app, swagger-ui page is not showing (returns a blank page) with errors in the console.

Minimal reproducible example

  1. Create a v18 Java project from start.vaadin.com
  2. Add the dependency
<dependencies>
    <dependency>
   <groupId>org.springdoc</groupId>
   <artifactId>springdoc-openapi-ui</artifactId>
   <version>1.5.5</version>
</dependency>
  1. Change Vaadin mapping to a different path using vaadin.urlMapping in application.properties. For example,
vaadin.url-mapping=/ui/*
  1. Run the server, and open http://localhost:8080/swagger-ui.html

Expected behavior

The Swagger UI page is opened

Actual behavior

Only a blank page is displayed with the following errors in the console image

Versions:

- Vaadin / Flow version: 18.0.6
- Java version: 11
- OS version: Windows

tarekoraby avatar Mar 02 '21 07:03 tarekoraby

Note, that Swagger UI seems to work fine in v14.X

tarekoraby avatar Mar 02 '21 07:03 tarekoraby

Same error on

  • Java version: 15
  • OS version: Mac

FDelporte avatar Mar 02 '21 08:03 FDelporte

The issue is most likely a generic one even though it's technically a Spring add-on issue.

denis-anisimov avatar Mar 09 '21 10:03 denis-anisimov

It needs to be exactly vaadin.urlMapping. vaadin.url-mapping will not work, even though your IDE might suggest it. It's not a regular Spring Boot configuration property and as such it's treated a bit differently that than you might expect.

Frettman avatar Feb 08 '22 00:02 Frettman

I am using vaadin flow 23, Java 17, Spring boot 2.7.0 and config not work.

image

Error message:

image

I think we don't need change vaadin base URL but we need config to set Vaadin servlet URL mapping having lowest priority in Spring. So it won't block other servlet mappings as CXF/swagger.

URL mapping priority maybe (Low to High): Spring servlet -> Vaadin servlet -> CXF/Swagger.

letrthang avatar Jun 11 '22 11:06 letrthang

I figured it out. And it appears to be a bug, but there is a simple way to avoid it.

Vaadin version 22.0.18 Spring Boot version 2.4.6

I had the following application.yaml

vaadin:
  url-mapping: /web/*

The problem is in this code below. Specifically in the name of the setting and how to get it by com.vaadin.flow.spring.RootMappedCondition.

public class RootMappedCondition implements Condition {

    public static final String URL_MAPPING_PROPERTY = "vaadin.urlMapping";

    @Override
    public boolean matches(ConditionContext context,
            AnnotatedTypeMetadata metadata) {
        return isRootMapping(
                context.getEnvironment().getProperty(URL_MAPPING_PROPERTY));
    }

We have the name of the setting "vaadin.urlMapping" in camelCase, and according to the Spring Boot specification it handles it by Relaxed Binding rules and for it vaadin.url-mapping == vaadin.urlMapping

BUT the way to get the setting context.getEnvironment().getProperty(URL_MAPPING_PROPERTY) knows nothing about these rules and only sees vaadin.urlMapping

To get the setting correctly, you need to get the VaadinConfigurationProperties bean from the context, but at this stage it is not in the context and the setting will not be resolved by Relaxed Binding rules from Spring Boot

So at this point you can easily bypass this problem and use the configuration name vaadin.urlMapping in application.yaml.

kochetkov-ma avatar Jul 02 '22 09:07 kochetkov-ma

Sounds like what was fixed in https://github.com/vaadin/flow/pull/13791

Artur- avatar Jul 02 '22 10:07 Artur-

The issue still happens even we change url-mapping. It is better to fix on issue #12949

letrthang avatar Jul 24 '22 04:07 letrthang

@letrthang, I have the same setup (based on your screenshots) and it works for me. spring/issues#602 contains some details why simply changing the orders of the URL mappings for Vaadin and Spring's resource handlers won't help. Also, judging from your screenshot, the issue in your case is that Spring handles Vaadin's path at /ui/, so letting Vaadin ignore requests to certain URLs and let them pass on to Spring, wouldn't really help. Or has the error changed now? Also, I can confirm that in the latest Vaadin version both vaadin.urlMapping and vaadin.url-mapping work now.

Frettman avatar Jul 24 '22 07:07 Frettman

@Frettman it still doesn't work for me. I cannot access restful resource using postman and also swagger UI page doesn't show up.

image image

letrthang avatar Jul 24 '22 07:07 letrthang

@letrthang, that error from your first screenshot is not from Vaadin; Vaadin would show something like in the image from this Stackoverflow question. Your error looks like something from Spring, so to me it seems like you have another issue. Have you tried accessing /swagger-ui/index.html directly? That's where /swagger-ui.html should get redirected to.

Frettman avatar Jul 24 '22 07:07 Frettman

@Frettman i created a test endpoint in vaadin demo project here, swagger still not work.

https://github.com/letrthang/vaadin23-flow-pro-components/blob/main/src/main/java/com/example/application/data/endpoint/TestSwaggerImpl.java

image

result:

image

Postman to send request also taken control by Vaadin handler:

image

letrthang avatar Jul 24 '22 08:07 letrthang

@tarekoraby @denis-anisimov may i know you have any plan to fix this issue ?

letrthang avatar Sep 14 '22 17:09 letrthang

@mshabarov, can someone from the Flow team please provide an update on this issue?

tarekoraby avatar Sep 15 '22 08:09 tarekoraby

This seems to work fine.

npx @vaadin/cli init swag-test
cd swag-test
# Add springdoc-openapi-ui dependency
# Add url mapping
mvn

opening http://localhost:4444/swagger-ui.html shows the swagger UI

Artur- avatar Sep 15 '22 09:09 Artur-

this config now will work with vaadin 23.2.1

vaadin.url-mapping=/web/*
springdoc.api-docs.path=/api/api-docs
springdoc.swagger-ui.path=/api/swagger-ui.html

However I prefer to get same config as Vaadin 14 as below which Vaadin home is root URL and allow to exclude swagger from root url (for now, this config is not working):

vaadin.url-mapping=/*
springdoc.api-docs.path=/api/api-docs
springdoc.swagger-ui.path=/api/swagger-ui.html

Anyway, there is other issue with open-api and Hilla:

Both springdoc-openapi-ui and Hilla using swagger-core and swagger-models with different versions, so causing swagger crashing.

Below config will work:

<properties>
        <java.version>17</java.version>
        <vaadin.version>23.2.1</vaadin.version>
        <hilla.version>1.2.1</hilla.version>
    </properties>
<dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.6.7</version>
            <!-- avoid conflict with hilla -->
            <exclusions>
                <exclusion>
                    <groupId>io.swagger.core.v3</groupId>
                    <artifactId>swagger-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.swagger.core.v3</groupId>
                    <artifactId>swagger-models</artifactId>
                </exclusion>
            </exclusions>
        </dependency> 

Below config will not work:

<properties>
        <java.version>17</java.version>
        <vaadin.version>23.2.1</vaadin.version>
        <hilla.version>1.2.1</hilla.version>
    </properties>
<dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.6.11</version>
            <!-- avoid conflict with hilla -->
            <exclusions>
                <exclusion>
                    <groupId>io.swagger.core.v3</groupId>
                    <artifactId>swagger-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.swagger.core.v3</groupId>
                    <artifactId>swagger-models</artifactId>
                </exclusion>
            </exclusions>
        </dependency> 
java.lang.NoSuchMethodError: 'io.swagger.v3.oas.models.media.ComposedSchema io.swagger.v3.oas.models.media.ComposedSchema.addAllOfItem(io.swagger.v3.oas.models.media.Schema)'
	at dev.hilla.generator.OpenAPIObjectGenerator.lambda$parseNonEndpointClassAsSchema$24(OpenAPIObjectGenerator.java:524) ~[endpoint-1.2.1.jar:na]
image

I submitted new issue to Hilla here: https://github.com/vaadin/hilla/issues/551

letrthang avatar Sep 15 '22 14:09 letrthang

Without the url mapping it seems that the Vaadin handler is invoked before the Swagger handler, preventing the swagger ui from showing. If this order is removed https://github.com/vaadin/flow/blob/master/vaadin-spring/src/main/java/com/vaadin/flow/spring/VaadinServletConfiguration.java#L61 the Swagger UI is shown but instead Vaadin views fail to render because of a 404

Artur- avatar Sep 16 '22 06:09 Artur-

@Artur-, it's what I described in detail in vaadin/spring#602 and an attempt at a solution in vaadin/spring#604. Let's just say setting the URL mapping is much easier ;)

Frettman avatar Sep 16 '22 06:09 Frettman

Thanks, I was just wondering if there really is no concept of "I want to handle some of the paths that match this mapping so ask me and if I say 'no thanks', then ask the next handler".

It sounds really impossible to be able to answer upfront "Will Vaadin handle this request" without actually letting Vaadin handle the request and see. The static cases like routes are easy, the dynamic code that you are able to add here and there is not.

Artur- avatar Sep 16 '22 06:09 Artur-

So if the resource handler and the Vaadin handler could be combined so that if the first returns 404, the second one is consulted then magically everything would work..

Artur- avatar Sep 16 '22 07:09 Artur-

This is fixed in https://github.com/vaadin/flow/pull/14579 but not in a fully automatic way. You can define paths to exclude, e.g. vaadin.excludeUrls=/swagger-ui/** and those will not be handled by the vaadin servlet when it is mapped to /*

Artur- avatar Oct 03 '22 07:10 Artur-