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.