Code review comment: you are right.`SqlToOperationConverter:557` is the root cause. I find the test case does not covert the full change path (not the whole commit), such as I remove the line in `TableEnvironmentImpl#1052`, ``` final CatalogFactory factory = TableFactoryService.find( 				CatalogFactory.class, 				properties); ``` The test case can also run successfully. Do we need build `StreamExecutionEnvironmentImpl` with user classloader directly to verify the change. 

Code before review:
public void testCreateCatalogFromUserClassLoader() throws Exception {
final String className = "UserCatalogFactory";
URLClassLoader classLoader = ClassLoaderUtils.withRoot(temporaryFolder.newFolder())
.addResource("META-INF/services/org.apache.flink.table.factories.TableFactory", "UserCatalogFactory")
.addClass(
className,
"import org.apache.flink.table.catalog.GenericInMemoryCatalog;\n" +
"import org.apache.flink.table.factories.CatalogFactory;\n" +
"import java.util.Collections;\n" +
"import org.apache.flink.table.catalog.Catalog;\n" +
"import java.util.HashMap;\n" +
"import java.util.List;\n" +
"import java.util.Map;\n" +
"\tpublic class UserCatalogFactory implements CatalogFactory {\n" +
"\t\t@Override\n" +
"\t\tpublic Catalog createCatalog(\n" +
"\t\t\t\tString name,\n" +
"\t\t\t\tMap<String, String> properties) {\n" +
"\t\t\treturn new GenericInMemoryCatalog(name);\n" +
"\t\t}\n" +
"\n" +
"\t\t@Override\n" +
"\t\tpublic Map<String, String> requiredContext() {\n" +
"\t\t\tHashMap<String, String> hashMap = new HashMap<>();\n" +
"\t\t\thashMap.put(\"type\", \"userCatalog\");\n" +
"\t\t\treturn hashMap;\n" +
"\t\t}\n" +
"\n" +
"\t\t@Override\n" +
"\t\tpublic List<String> supportedProperties() {\n" +
"\t\t\treturn Collections.emptyList();\n" +
"\t\t}\n" +
"\t}"
).build();
try (TemporaryClassLoaderContext context = TemporaryClassLoaderContext.of(classLoader)) {
TableEnvironment tableEnvironment = getTableEnvironment();
tableEnvironment.executeSql("CREATE CATALOG cat WITH ('type'='userCatalog')");
assertTrue(tableEnvironment.getCatalog("cat").isPresent());
}
}

Line under review: try (TemporaryClassLoaderContext context = TemporaryClassLoaderContext.of(classLoader)) {

Code after addressing the review:
public void testCreateCatalogFromUserClassLoader() throws Exception {
final String className = "UserCatalogFactory";
URLClassLoader classLoader = ClassLoaderUtils.withRoot(temporaryFolder.newFolder())
.addResource("META-INF/services/org.apache.flink.table.factories.TableFactory", "UserCatalogFactory")
.addClass(
className,
"import org.apache.flink.table.catalog.GenericInMemoryCatalog;\n" +
"import org.apache.flink.table.factories.CatalogFactory;\n" +
"import java.util.Collections;\n" +
"import org.apache.flink.table.catalog.Catalog;\n" +
"import java.util.HashMap;\n" +
"import java.util.List;\n" +
"import java.util.Map;\n" +
"\tpublic class UserCatalogFactory implements CatalogFactory {\n" +
"\t\t@Override\n" +
"\t\tpublic Catalog createCatalog(\n" +
"\t\t\t\tString name,\n" +
"\t\t\t\tMap<String, String> properties) {\n" +
"\t\t\treturn new GenericInMemoryCatalog(name);\n" +
"\t\t}\n" +
"\n" +
"\t\t@Override\n" +
"\t\tpublic Map<String, String> requiredContext() {\n" +
"\t\t\tHashMap<String, String> hashMap = new HashMap<>();\n" +
"\t\t\thashMap.put(\"type\", \"userCatalog\");\n" +
"\t\t\treturn hashMap;\n" +
"\t\t}\n" +
"\n" +
"\t\t@Override\n" +
"\t\tpublic List<String> supportedProperties() {\n" +
"\t\t\treturn Collections.emptyList();\n" +
"\t\t}\n" +
"\t}"
).build();
try (TemporaryClassLoaderContext context = TemporaryClassLoaderContext.of(classLoader)) {
TableEnvironment tableEnvironment = getTableEnvironment();
tableEnvironment.executeSql("CREATE CATALOG cat WITH ('type'='userCatalog')");
assertTrue(tableEnvironment.getCatalog("cat").isPresent());
}
}