My project works if compiled on Linux but does not work when compiled on Mac. When I diffed the jars the only difference was the order of the files in the jar. I tried to create a demo project to reproduce it, but it doesn't reproduce without manual intervention. Seems by chance the demo project puts the classes in the correct order.
But if I manually re-order the files in the compiled jar so that they are similar to how a Mac compiles my actual project, then the issue does indeed reproduce.
bash-3.2$ unzip demo-working.jar
bash-3.2$ zip -sf demo-working.jar > correct_order.txt
# Manually remove these lines from the txt file (the first and last lines in the file):
# Archive contains:
# Total 107 entries (9817236 bytes)
bash-3.2$ for F in $(cat broken_order.txt); do zip -0 demo-broken.jar "$F"; done
bash-3.2$ diff correct_order.txt broken_order.txt
83,85d82
< BOOT-INF/classes/com/example/demo/MyGateway.class
< BOOT-INF/classes/com/example/demo/MyDao.class
< BOOT-INF/classes/com/example/demo/MyUseCase.class
86a84,86
> BOOT-INF/classes/com/example/demo/MyUseCase.class
> BOOT-INF/classes/com/example/demo/MyDao.class
> BOOT-INF/classes/com/example/demo/MyGateway.class
If the Gateway appears in the jar before the UseCase, then it works. If it appears after, then it does not work.
When it works, I can see this in the logs:
============================
CONDITIONS EVALUATION REPORT
============================
Negative matches:
-----------------
MyConfiguration:
Did not match:
- @ConditionalOnProperty (database-common.datasource.url) did not find property 'database-common.datasource.url' (OnPropertyCondition)
MyDao:
Did not match:
- @ConditionalOnBean (types: com.example.demo.MyConfiguration; SearchStrategy: all) did not find any beans of type com.example.demo.MyConfiguration (OnBeanCondition)
MyUseCase:
Did not match:
- @ConditionalOnBean (types: com.example.demo.MyGateway; SearchStrategy: all) did not find any beans of type com.example.demo.MyGateway (OnBeanCondition)
And when it does not work, I can see this in the logs
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
MyUseCase matched:
- @ConditionalOnBean (types: com.example.demo.MyGateway; SearchStrategy: all) found bean 'myDao' (OnBeanCondition)
Negative matches:
-----------------
MyConfiguration:
Did not match:
- @ConditionalOnProperty (database-common.datasource.url) did not find property 'database-common.datasource.url' (OnPropertyCondition)
MyDao:
Did not match:
- @ConditionalOnBean (types: com.example.demo.MyConfiguration; SearchStrategy: all) did not find any beans of type com.example.demo.MyConfiguration (OnBeanCondition)
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.demo.MyUseCase required a bean of type 'com.example.demo.MyGateway' that could not be found.
Action:
Consider defining a bean of type 'com.example.demo.MyGateway' in your configuration.
I'm using
id 'org.springframework.boot' version '3.1.3'
MyUseCase.java
package com.example.demo;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
@Service
@ConditionalOnBean(MyGateway.class)
public class MyUseCase {
MyGateway myGateway;
public MyUseCase(MyGateway myGateway) {
this.myGateway = myGateway;
}
}
MyGateway.java
package com.example.demo;
public interface MyGateway {
}
MyDao.java
package com.example.demo;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
@Service
@ConditionalOnProperty(name = "database-common.datasource.url")
public class MyDao implements MyGateway {
public MyDao() {
}
}
MyConfiguration.java
package com.example.demo;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
@ConditionalOnProperty(name = "database-common.datasource.url")
@Configuration
public class MyConfiguration {
}
Comment From: wilkinsona
Duplicates https://github.com/spring-projects/spring-boot/issues/37382.