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 :-)
Comment From: bclozel
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:
- http://localhost:8080/ shows a
test.jsp
page importing a CSS resource with a hash suffix - http://localhost:8082/actuator/ shows the actuator endpoints
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!
Comment From: derTobsch
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.
Comment From: grafjo
@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!
Comment From: bclozel
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,
Comment From: derTobsch
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 :)
Comment From: bclozel
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?
Comment From: derTobsch
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!
Comment From: grafjo
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!
Comment From: derTobsch
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??
Comment From: bclozel
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.
Comment From: derTobsch
Hey @bclozel, I added a PR to your minimal example (https://github.com/bclozel/gh-25113/pull/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
Comment From: derTobsch
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 https://github.com/bclozel/gh-25113/pull/2
Comment From: bclozel
Thanks for helping out here, this is a hard one to figure out.
To reproduce this issue, we need the following:
- A Spring Boot application with actuator and a separate management context
- A resource chain configured (here for content-based hashing)
- 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!
Comment From: derTobsch
Good Morning @bclozel, that was a nice journey with you. Thanks for your time and support! :)
Comment From: bclozel
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.