Protocol resolver from parent context is not used in binder context
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 45/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Stale
- Tech stack
- java, spring, spring-boot
- Domain
- backend
Research direction
Start with DefaultBinderFactory.initializeBinderContextSimple and the CustomProtocolResolverBindingTest reproduction. Run the test and trace how the child binding context is created; done means the context resolves the backwards:// resource through the parent protocol resolver and the assertions pass.
Written by the indexing model from the issue text.
Description
Describe the issue
When a binder context is created in DefaultBinderFactory, the protocol resolvers from parent context are not copied to the binder context. In our case it breaks our application because we have a protocol resolver that makes sure that the kafka truststore is a local file (by downloading it), and org.springframework.boot.autoconfigure.kafka.KafkaProperties.Ssl#resourceToPath fails if it is not on file system. I.e. it fails because the protocol resolver is not applied in the binding context, and the KafkaProperties bean is created in that context.
This is caused by the fix for https://github.com/spring-projects/spring-boot/issues/41487 where configuration properties beans are re-created in child contexts rather than inherited from the parent context. I'll leave it for you to evaluate if a fix should go into spring-boot or spring-cloud-stream. E.g. should the protocol resolvers be explicitly copied when creating the child context here? Or should protocol resolvers be automatically inherited from parent context?
To Reproduce
I create this test to demonstrate the issue:
package org.springframework.cloud.stream.binder;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.stream.config.BinderFactoryAutoConfiguration;
import org.springframework.cloud.stream.config.BindingServiceConfiguration;
import org.springframework.cloud.stream.function.FunctionConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.FileUrlResource;
import org.springframework.core.io.ProtocolResolver;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import java.net.URI;
import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class CustomProtocolResolverBindingTest {
@Test
void bindingContextUsesParentProtocolResolvers() {
new ApplicationContextRunner()
.withInitializer(ctx -> ctx.addProtocolResolver(new CustomProtocolResolver()))
.withPropertyValues("test.resource=backwards://foo-bar")
.withConfiguration(AutoConfigurations.of(BinderFactoryAutoConfiguration.class,
BindingServiceConfiguration.class, FunctionConfiguration.class))
.withUserConfiguration(AppConfig.class)
.run(ctx -> {
DefaultBinderFactory defaultBinderFactory = ctx.getBean(DefaultBinderFactory.class);
ConfigurableApplicationContext bindingContext = defaultBinderFactory.initializeBinderContextSimple("mock",
Collections.emptyMap(),
new BinderType("custom-resolvers", new Class[]{AppConfig.class}),
new BinderConfiguration("custom-resolvers", Collections.emptyMap(), true, true),
true);
TestProperties props = bindingContext.getBean(TestProperties.class);
assertNotNull(props);
assertNotNull(props.getResource());
assertInstanceOf(FileUrlResource.class, props.getResource());
assertEquals("file://rab-oof", props.getResource().getURI().toString());
});
}
@SpringBootApplication
@EnableConfigurationProperties(TestProperties.class)
static class AppConfig {
}
@ConfigurationProperties(prefix = "test")
static class TestProperties {
private Resource resource;
public Resource getResource() {
return resource;
}
public void setResource(Resource resource) {
this.resource = resource;
}
}
/**
* Custom protocol resolver that handles the "backwards" scheme by replacing it with the
* "file" scheme and reversing the host part.
*/
static class CustomProtocolResolver implements ProtocolResolver {
@Override
public Resource resolve(String location, ResourceLoader resourceLoader) {
URI uri = URI.create(location);
if (uri.getScheme().equals("backwards")) {
String reversed = new StringBuilder(uri.getHost()).reverse().toString();
return resourceLoader.getResource("file://" + reversed);
}
return null;
}
}
}
Version of the framework
4.2.1 (with spring-boot 3.4.3)
Expected behavior
Protocol resolvers are applied also in the child context.
- Dominant language
- Java
- Stars
- 1.1k
- Forks
- 646
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 8
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from spring-cloud/spring-cloud-stream
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
spring-cloud/spring-cloud-stream#3268 · 1 comment ·
-
bug
spring-cloud/spring-cloud-stream#3257 · 2 comments · 2 reactions · 1 assignee ·
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
spring-cloud/spring-cloud-stream#3242 · 1 comment ·
-
Backport 4.3.x bug
spring-cloud/spring-cloud-stream#3211 · 3 comments · 1 assignee ·
-
bug
spring-cloud/spring-cloud-stream#3208 · 4 comments · 1 reaction · 1 assignee ·
All issues in spring-cloud/spring-cloud-stream
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
infinispan/infinispan#18150 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
opensearch-project/k-NN#3597 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100