Repository: spring-projects/spring-framework
File: spring-jdbc/src/main/java/org/springframework/jdbc/config/SortedResourcesFactoryBean.java (Java)

Code before:
	public void setResourceLoader(ResourceLoader resourceLoader) {
		this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
	}


	@Override
	public Class<? extends Resource[]> getObjectType() {
		return Resource[].class;
	}

	@Override
	protected Resource[] createInstance() throws Exception {
		List<Resource> scripts = new ArrayList<>();
		for (String location : this.locations) {
			List<Resource> resources = new ArrayList<>(
					Arrays.asList(this.resourcePatternResolver.getResources(location)));
			resources.sort((r1, r2) -> {
				try {
					return r1.getURL().toString().compareTo(r2.getURL().toString());
				}
				catch (IOException ex) {
					return 0;
				}
			});
			scripts.addAll(resources);
		}
		return scripts.toArray(new Resource[0]);
	}

}


Review comment (bug):
> This change maintains the same output behavior while improving performance and error handling.

Are you guys sure about the "maintains the same output behavior" bit?

We're getting the following in Spring Boot 3.5.8 and [lbruun/Pre-Liquibase](https://github.com/lbruun-net/Pre-Liquibase):
```
Caused by: java.lang.IllegalStateException: Error when creating Resource object from "classpath:preliquibase/postgresql.sql"
        at net.lbruun.springboot.preliquibase.PreLiquibase.doGetResources(PreLiquibase.java:288)
        at net.lbruun.springboot.preliquibase.PreLiquibase.getResourcesFromStringLocations(PreLiquibase.java:266)
        at net.lbruun.springboot.preliquibase.PreLiquibase.getScripts(PreLiquibase.java:255)
        at net.lbruun.springboot.preliquibase.PreLiquibase.execute(PreLiquibase.java:127)
        at net.lbruun.springboot.preliquibase.PreLiquibaseAutoConfiguration.preLiquibase(PreLiquibaseAutoConfiguration.java:100)
        at java.base/java.lang.reflect.Method.invoke(Method.java:569)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:172)
        ... 104 more
Caused by: java.lang.IllegalStateException: Failed to resolve URL for resource [class path resource [preliquibase/postgresql.sql]] from location pattern [classpath:preliquibase/postgresql.sql]
        at org.springframework.jdbc.config.SortedResourcesFactoryBean.createInstance(SortedResourcesFactoryBean.java:86)
        at org.springframework.jdbc.config.SortedResourcesFactoryBean.createInstance(SortedResourcesFactoryBean.java:44)
        at org.springframework.beans.factory.config.AbstractFactoryBean.afterPropertiesSet(AbstractFactoryBean.java:142)
        at net.lbruun.springboot.preliquibase.PreLiquibase.doGetResources(PreLiquibase.java:285)
        ... 110 more
Caused by: java.io.FileNotFoundException: class path resource [preliquibase/postgresql.sql] cannot be resolved to URL because it does not exist
        at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:230)
        at org.springframework.jdbc.config.SortedResourcesFactoryBean.createInstance(SortedResourcesFactoryBean.java:83)
        ... 113 more
```
See https://github.com/lbruun-net/Pre-Liquibase/blob/1.6.1/autoconfigure/src/main/java/net/lbruun/springboot/preliquibase/PreLiquibase.java#L286

There is no such issue in SB 3.5.7.

FYI @lbruun

_Edit/disclaimer:_ We're using `src/main/resources/preliquibase/default.sql`, but no `postgresql.sql`.

Code after:

	@Override
	public void setResourceLoader(ResourceLoader resourceLoader) {
		this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
	}


	@Override
	public Class<? extends Resource[]> getObjectType() {
		return Resource[].class;
	}

	@Override
	protected Resource[] createInstance() throws Exception {
		List<Resource> scripts = new ArrayList<>();
		for (String location : this.locations) {
			Resource[] resources = this.resourcePatternResolver.getResources(location);

			// Cache URLs to avoid repeated I/O during sorting
			Map<Resource, String> urlCache = new LinkedHashMap<>(resources.length);
			for (Resource resource : resources) {
				try {
					urlCache.put(resource, resource.getURL().toString());
				}
				catch (IOException ex) {
					throw new IllegalStateException(
							"Failed to resolve URL for resource [" + resource +
									"] from location pattern [" + location + "]", ex);
				}
			}

			// Sort using cached URLs
			List<Resource> sortedResources = new ArrayList<>(urlCache.keySet());
			sortedResources.sort(Comparator.comparing(urlCache::get));

			scripts.addAll(sortedResources);
		}
		return scripts.toArray(new Resource[0]);
	}

}