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

Missing resource handling configuration when separate management context is configured #25113

Closed
derTobsch opened this issue Feb 5, 2021 · 15 comments
Assignees
Labels
for: external-project For an external project and not something we can fix status: superseded An issue that has been superseded by another

Comments

@derTobsch
Copy link

derTobsch commented Feb 5, 2021

If we configure the management.server.port and this one is not equal to server.port via spring.web.resources.chain.strategy.content.* generation of the hash does not work and we do not get the correct hashs on the files. If there are some information about this in docs please hint me to it. Otherwise here are an example how to reproduce it:

Id you start this docker-compose file everything will be configured for you and the hashing of the assets in /css/** e.g. does work.
Take a look at http://localhost:8080/login with the developer console in Chrome/Firefox e.g. and see that the style.css e.g. does have a hash and if we add the MANAGEMENT_SERVER_PORT=8081 we do not see the hashes.
The common.$hash.css file can be ignored this is not placed in /css/** and will be generated via webpack.

version: '2.4'
services:
  mariadb:
    image: mariadb:10.5
    ports:
      - '3308:3306'
    environment:
      - MYSQL_DATABASE=urlaubsverwaltung
      - MYSQL_USER=urlaubsverwaltung
      - MYSQL_PASSWORD=urlaubsverwaltung
      - MYSQL_RANDOM_ROOT_PASSWORD=yes
  mailhog:
    image: mailhog/mailhog:v1.0.0
    ports:
      - '1025:1025'
      - '8025:8025'
  uv:
    image: synyx/urlaubsverwaltung:latest
    ports:
      - '8080:8080'
    environment:
      - SPRING_MAIL_HOST=mailhog
      - SPRING_MAIL_PORT=1025
      - UV_MAIL_SENDER=test@lala.de
      - UV_MAIL_ADMINISTRATOR=test@lala.de
      - UV_MAIL_APPLICATION-URL=http://localhost:8080
      - SPRING_DATASOURCE_URL=jdbc:mariadb://mariadb:3306/urlaubsverwaltung
      - UV_SECURITY_AUTH=default

But know if I add the management.server.port the hash of /css/** files e.g. is not generated

version: '2.4'
services:
  mariadb:
    image: mariadb:10.5
    ports:
      - '3308:3306'
    environment:
      - MYSQL_DATABASE=urlaubsverwaltung
      - MYSQL_USER=urlaubsverwaltung
      - MYSQL_PASSWORD=urlaubsverwaltung
      - MYSQL_RANDOM_ROOT_PASSWORD=yes
  mailhog:
    image: mailhog/mailhog:v1.0.0
    ports:
      - '1025:1025'
      - '8025:8025'
  uv:
    image: synyx/urlaubsverwaltung:latest
    ports:
      - '8080:8080'
    environment:
      - SPRING_MAIL_HOST=mailhog
      - SPRING_MAIL_PORT=1025
      - UV_MAIL_SENDER=test@lala.de
      - UV_MAIL_ADMINISTRATOR=test@lala.de
      - UV_MAIL_APPLICATION-URL=http://localhost:8080
      - SPRING_DATASOURCE_URL=jdbc:mariadb://mariadb:3306/urlaubsverwaltung
      - UV_SECURITY_AUTH=default
      - MANAGEMENT_SERVER_PORT=8081

The default application properties that we add in the given docker container can be seen here https://github.com/synyx/urlaubsverwaltung/blob/master/src/main/resources/application.properties#L30

Do you have any information for us, if this is a common behaviour and how we can achieve having hashed css files and split the server and management port?

Hint: This is independent from docker. I have the same behaviour via ide, 'java -jar ...' and so on :-)

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Feb 5, 2021
@bclozel bclozel self-assigned this Feb 5, 2021
@bclozel bclozel added the status: waiting-for-feedback We need additional information before we can continue label Feb 5, 2021
@bclozel
Copy link
Member

bclozel commented Feb 5, 2021

I've spent some time trying to reproduce this issue, no success so far.
Here's a sample project: https://github.com/bclozel/gh-25113

With that project, you can run java -jar target/gh25113-0.0.1-SNAPSHOT.war and see that:

In order to rewrite URLs in templates, Spring Boot is contributing a ResourceUrlEncodingFilter to the application context. My best guess is that your custom setup (maybe this? is preventing this Filter from being involved when a separate management port is configured.

At this point I'm suspecting an error in your setup. If you believe this is a bug in Spring Boot, please build on top of my sample to have a minimal repro for this issue.

Thanks!

@derTobsch
Copy link
Author

derTobsch commented Feb 5, 2021

Thanks for your example @bclozel! I will take a look at it as soon I can and give you feedback.

We also disabled the jsp precompile that you mentioned in your post with the configuration but without success.

I will take a deeper look soon.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 5, 2021
@bclozel bclozel added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Feb 5, 2021
@grafjo
Copy link
Contributor

grafjo commented Feb 10, 2021

@bclozel thanks for your sample project. I can not reproduce your sample project that http://localhost:8080 includes the CSS resource a hash suffix.

Example curl request for the java -jar target/gh25113-0.0.1-SNAPSHOT.war command:

Note: The jsessionid=87F1FDB8CC4C56A613914C475F0EB70A is not the expected hash

curl localhost:8080 -v
*   Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 
< Set-Cookie: JSESSIONID=87F1FDB8CC4C56A613914C475F0EB70A; Path=/; HttpOnly
< Content-Type: text/html;charset=UTF-8
< Content-Language: en-US
< Content-Length: 164
< Date: Wed, 10 Feb 2021 21:28:49 GMT
< 



<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="/css/style.css;jsessionid=87F1FDB8CC4C56A613914C475F0EB70A" />
</head>
<body>
TEST
</body>
* Connection #0 to host localhost left intact
</html>

Can you please provide the output of your curl?

Big thx!

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 10, 2021
@bclozel
Copy link
Member

bclozel commented Feb 11, 2021

Sorry I missed the important part in my repro: declaring the ResourceUrlEncodingFilter, as described in the reference documentation.

Now my sample shows:

$ http :8080
HTTP/1.1 200
Connection: keep-alive
Content-Language: en-FR
Content-Length: 197
Content-Type: text/html;charset=UTF-8
Date: Thu, 11 Feb 2021 12:33:31 GMT
Keep-Alive: timeout=60
Set-Cookie: JSESSIONID=2C1498FBEAE8EFCFD37409F7FB0A79A3; Path=/; HttpOnly

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="/css/style-1688c8210b6509d702b1adb96bc4d0f3.css;jsessionid=2C1498FBEAE8EFCFD37409F7FB0A79A3" />
</head>
<body>
TEST
</body>
</html>

Thanks,

@bclozel bclozel added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Feb 11, 2021
@derTobsch
Copy link
Author

Thanks for your Example @bclozel. I took a first look into it and defined the ResourceUrlEncodingFilter and the application will not start because we use Freemarker Templating for our Emails and the FreeMarkerServletWebConfiguration is already defining a ResourceUrlEncodingFilter for us. Therefore, without knowing, we had already the ResourceUrlEncodingFilter bean.
This is also ok and makes sense because the hashes are there.

But now to the strange part. If I run the application via mvn spring-boot:run the application does not start, because of the duplicated ResourceUrlEncodingFilter see:

Description:

The bean 'resourceUrlEncodingFilter', defined in class path resource [org/synyx/urlaubsverwaltung/web/jsp/ConfigurationJsp.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/boot/autoconfigure/freemarker/FreeMarkerServletWebConfiguration.class] and overriding is disabled.

This is not strange at all. Because we now have duplicated beans. Ok.

But if I build a war and let it run, everything works, no duplicated beans, and the hashes are there. But if I add the management.server.port again the hashes are gone.

So what does the FreeMarkerServletWebConfiguration do or not do or something else if I add the management.server.port?

Maybe you have some hints for us, before we start debugging in this rabbit hole :)

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 11, 2021
@bclozel
Copy link
Member

bclozel commented Feb 11, 2021

I don't understand why spring-boot:run and running as a WAR is different here.
My advice would be to run the application both ways with debug enabled and collect and compare auto-configuration reports. Maybe something is being configured in one case and not the other?

@bclozel bclozel added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Feb 11, 2021
@derTobsch
Copy link
Author

I don't understand why spring-boot:run and running as a WAR is different here.
My advice would be to run the application both ways with debug enabled and collect and compare auto-configuration reports. Maybe something is being configured in one case and not the other?

I thought the same. Will have a look at it tomorrow. Thanks for your help an input!

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 11, 2021
@bclozel bclozel added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Feb 11, 2021
@grafjo
Copy link
Contributor

grafjo commented Feb 12, 2021

Hi @bclozel,
after a lot of fiddling around in WebMvcAutoConfiguration and ResourceUrlProvider I can confirm that everything works as expected!

Our application is using springfox-boot-starter in version 3.0.0 and it seems that there is an issue running managment server on a different port.

I don't know why, but in https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java#L140 there are just beans available e.g. resourceHandlerMapping using /swagger-ui/**-pattern instead /**.

I checkt the springfox autoconfiguration. In https://github.com/springfox/springfox/blob/master/springfox-boot-starter/src/main/java/springfox/boot/starter/autoconfigure/SwaggerUiWebMvcConfigurer.java#L20 there is a registration of an additional ResourceHandler. I don't get it why running the management server on the same port is working and on a different port not.

Big thanks for your support mate!

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 12, 2021
@derTobsch
Copy link
Author

derTobsch commented Feb 12, 2021

I replaced SpringFox with SpringDoc and I have the exact same behaviour see https://github.com/synyx/urlaubsverwaltung/tree/springdoc and if I remove both, springfox and springdoc, everything is working as expected. So why and what does the change of the management.server.port do to this libs?! I don't get it.

@bclozel are there different RessourceHandler if I add management.server.port and therefore the chain cannot hash??

@bclozel
Copy link
Member

bclozel commented Feb 12, 2021

At this point it seems we've established that this is likely to be an issue with those libraries, not Spring Boot.

I'll leave this issue opened until we have a better understanding.

Please provide the requested information: the auto-configuration reports for both variants (with the hash and without it). This should help us narrow down the source of the problem.

@bclozel bclozel added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Feb 12, 2021
@derTobsch
Copy link
Author

derTobsch commented Feb 12, 2021

Hey @bclozel,
I added a PR to your minimal example (bclozel/gh-25113#1) that shows, when

@Configuration
public class ResourceHandlerConfiguration implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("/something/**");
    }
}

a ResourceHandler is added via WebMvcConfigurer the hashing does not work, when the management.server.port != server.port. That does not feel like a default behaviour to me, or?

If you debug into https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java#L140 with a different management.server.port than server.port you only see two times the /something/** pattern and if you change the management.server.port to be equal to server.port than there are the following patterns: /something/**, /webjars/** and /**.

I also added the debug output with and without different ports and a diff of it.

with-resource-handler-and-management-the-same.log
with-resource-handler-and-management-different-management-server-port.log
diff-diferent-and-same-menagement-server-port.log

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 12, 2021
@derTobsch
Copy link
Author

derTobsch commented Feb 12, 2021

I gave it another try after thinking about it, and thought why not downgrade to the latest version thiat is working, because I had the feeling that it is a Spring Boot bug. And there it is I can only reproduce the bug with Spring Boot 2.4.2 and 2.3.8. With 2.4.1 and 2.3.7 and added management.server.port that is not equal the server.port the behaviour is as expected.

I added another PR to your example where I downgraded the application to 2.4.1 see bclozel/gh-25113#2

@bclozel bclozel added this to the 2.3.9 milestone Feb 12, 2021
@bclozel bclozel added type: regression A regression from a previous release and removed status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged labels Feb 12, 2021
@bclozel
Copy link
Member

bclozel commented Feb 12, 2021

Thanks for helping out here, this is a hard one to figure out.

To reproduce this issue, we need the following:

  1. A Spring Boot application with actuator and a separate management context
  2. A resource chain configured (here for content-based hashing)
  3. A separate WebMvcConfigurer that adds a new resource handling registration

The sample application is here.

Here's what's happening:

  1. the custom resource handling registration is registered
  2. the child application context publishes the refreshed context event
  3. the ResourceUrlProvider auto-detects the resource handlers and registers the location, then locks itself from further modifications. At this point the Spring Boot resource registrations are not registered and are ignored at runtime when resolving URLs for resources.
  4. After that, Spring Boot registers its resource handling configuration; another refreshed event is published but this is too late since ResourceUrlProvider now doesn't allow further modifications.

The expected order is to switch 4) and 3) so that Spring Boot's resource handling configuration is detected.

I think this could be related to #24748 (and since this is a forward port, its parent issues).
The strange part is that I can reproduce this regression with 2.4.2 and 2.3.8.RELEASE, but not 2.2.13.RELEASE where #24745 was originally applied.

It seems that having a parent/child context setup involves an event being fired before the resource handling configuration is processed in the parent. We'll need more time to figure out what is the problem exactly - I'll update my sample application right away.

Thanks!

@bclozel bclozel changed the title spring.web.resources.chain.strategy.content.* does not work if management.server.port != server.port Missing resource handling configuration when separate management context is configured Feb 12, 2021
@derTobsch
Copy link
Author

Good Morning @bclozel, that was a nice journey with you. Thanks for your time and support! :)

@bclozel
Copy link
Member

bclozel commented Feb 17, 2021

While something might have changed in Spring Boot that alters the ordering of those parent/child context events in some way, we've found that the main issue here is that the ResourceUrlProvider component should not consider events that are not sent by its own application context.

We're closing this issue and marking it as superseded by spring-projects/spring-framework#26561 (and spring-projects/spring-framework#26562 for the backport).

This will be fixed in Spring Boot 2.4.4, since it will pick up the upcoming Spring Framework 5.3.5 release.

@bclozel bclozel closed this as completed Feb 17, 2021
@bclozel bclozel added for: external-project For an external project and not something we can fix status: superseded An issue that has been superseded by another and removed type: regression A regression from a previous release labels Feb 17, 2021
@bclozel bclozel removed this from the 2.3.x milestone Feb 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project For an external project and not something we can fix status: superseded An issue that has been superseded by another
Projects
None yet
Development

No branches or pull requests

5 participants