spring-projects / spring-boot

Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.
https://spring.io/projects/spring-boot
Apache License 2.0
75.19k stars 40.69k forks source link

Apply TomcatConnectorCustomizer and TomcatContextCustomizer beans automatically #15062

Closed philwebb closed 5 years ago

philwebb commented 6 years ago

Hi, this is a first-timers-only issue. This means we've worked to make it more legible to folks who either haven't contributed to our codebase before, or even folks who haven't contributed to open source before.

If that's you, we're interested in helping you take the first step and can answer questions and help you out as you do. Note that we're especially interested in contributions from people from groups underrepresented in free and open source software!

If you have contributed before, consider leaving this one for someone new, and looking through our general ideal-for-contribution issues. Thanks!

Background

Spring Boot provides a number of callback interfaces that can be used to customize the web server. For Tomcat, a TomcatConnectorCustomizer can be used to customize a Tomcat Connector and a TomcatContextCustomizer can be used to customize a Tomcat Context.

Problem

The customizers can be configured via the addConnectorCustomizers() and addContextCustomizers() methods on the ConfigurableTomcatWebServerFactory. This is bit tedious as can be seen from the example below:

@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> connectorCustomizer() {
    return (tomcat) -> {
        tomcat.addConnectorCustomizers(
            (connector) -> ((AbstractHttp11Protocol<?>) connector
                .getProtocolHandler()).setProcessorCache(250)); // example connector customization
    };
}

Instead, if we applied TomcatConnectorCustomizer and TomcatContextCustomizer beans automatically, that would simplify the configuration to the following:

@Bean
public TomcatConnectorCustomizer processorCacheCustomizer() {
    return (connector) ->  (connector) -> ((AbstractHttp11Protocol<?>) connector
                .getProtocolHandler()).setProcessorCache(250)); // example connector customization
}

Solution

Beans of both the TomcatContextCustomizer and TomcatConnectorCustomizer types should be applied automatically to TomcatServletWebServerFactory and TomcatReactiveWebServerFactory. For TomcatServletWebServerFactory, this can be done here and the configuration for the reactive one can be found here.

The ObjectProvider interface can be used for injecting a dependency. Here is an example that can be used to inject customizers when there can be 0..n of them.

Tests for the servlet and reactive versions are here and here respectively.

Steps to Fix

philwebb commented 6 years ago

See also #15035

govi20 commented 6 years ago

I would like to work on this issue.

mbhave commented 6 years ago

@govi20 Sure! Feel free to ask any questions you might have. We'll look forward to your Pull Request.

wilkinsona commented 6 years ago

We already have a PR from you, @govi20. Thank you for that. In the spirit of first-timers only can we please carry on working with you on that and leave this issue for someone who hasn’t contributed before?

nishantraut commented 6 years ago

Hi @wilkinsona can i work on this?

wilkinsona commented 6 years ago

@nishantraut Thank you for the offer, but you have already contributed as well. This issue is intended especially for someone new.

nishantraut commented 6 years ago

Yes @wilkinsona that was documentation update. How can i identify and pickup small issues in code.

wilkinsona commented 6 years ago

@nishantraut Please look at the ideal-for-contribution label as recommended above.

xoronet commented 6 years ago

Hi, i would like to try it!

wilkinsona commented 6 years ago

Great stuff. Thank you, @xoronet. Please feel free to asking any questions you may have and we’ll look forward to your pull request.

govi20 commented 6 years ago

I am yet to make the contribution, as per Stephane my pull request does not cover all the requirements and issue is very complex. Anyways, will work on something else.

sadath42 commented 6 years ago

Should i create a branch from the master or should i fork the master

wilkinsona commented 6 years ago

@sadath42 Thanks for offering to work on this but @xoronet is already doing so. Please keep an eye out for other first-timers-only issues in the future and we'll be happy to guide you through the process once you've claimed an issue.

wilkinsona commented 5 years ago

How's it going, @xoronet? If you have any questions, please feel free to ask them here and we'll do our best to help.

ihrigb commented 5 years ago

If @xoronet is no longer available to look into this, I could take a shot. Just let me know.

TheCloutEngineer commented 5 years ago

Do you have any other first-timers issues?

xoronet commented 5 years ago

Hi @wilkinsona, fine so far. I have forked, cloned and build the project. I also digged into the topic as well as into the code. Unfortunately I had to focus on a work related project in the last days. Furthermore I had to check if my employee allows me to sign the CLA. No problems from his side. I will go back to solving the issue on Monday. Is there a date until the issue should be finished?

wilkinsona commented 5 years ago

Great, thank you. The issue's currently in the 2.1.x milestone and 2.1.1 is scheduled for 27 November. It would be nice, although it's not essential, for the issue to be fixed before then.

wilkinsona commented 5 years ago

@Ksaboor You can find other first-timer-only issues by clicking on the label. At the time of writing this is the only such open first-timers issue.

Razi007 commented 5 years ago

can i try to contribute here now.

xoronet commented 5 years ago

Hi team, I am terrible sorry but I am not able to work on the topic because of too much other tasks at work. I dont find enough time, so I think it would be the best to return the issue to the crowd. I am terrible sorry for wasting your time! @philwebb @wilkinsona @Razi007

wilkinsona commented 5 years ago

Thanks for letting us know, @xoronet.

@ihrigb I think you were next in line. Would you like to take this one on?

ihrigb commented 5 years ago

@wilkinsona, yes I will take care of it.

wilkinsona commented 5 years ago

Sorry, @ihrigb. I've just noticed that you've already made two contributions to the project. Thank you again for those. As a first timers only issue, this issue is intended for someone who has never contributed to the project before so that we can help them to get started and find their feet.

@Ksaboor I think you're next in line. Would you like to take this one on?

TheCloutEngineer commented 5 years ago

Yes I'll take this on. Thanks for this opportunity!

wilkinsona commented 5 years ago

Great! Thank you, @Ksaboor. If you have any questions, please don't hesitate to ask here.

ihrigb commented 5 years ago

@wilkinsona, ok. Although these must be years back. I guess then "ideal-for-contribution" is what I rather should look for?

wilkinsona commented 5 years ago

@ihrigb Yes, that's right. Thank you.

Raheela1024 commented 5 years ago

Hi, can I work on it now?

wilkinsona commented 5 years ago

Thank you for the offer, @Raheela1024, but @Ksaboor is working on this one.

TheCloutEngineer commented 5 years ago

@wilkinsona @philwebb

Sorry for the delay on working this.

From my understanding, I'm applying the TomcatConnectorCustomizer and TomcatContextCustomizer beans to the ServletWebServerFactoryConfiguration and ReactiveWebServerFactoryConfiguration.

Am I implementing the two blocks of code into ServletWebServerFactoryConfiguration class and the ReactiveWebServerFactoryConfiguration class?

wilkinsona commented 5 years ago

The two blocks of code above are an illustration of how the changes proposed here will improve things for users. In terms of implementing the proposed changes, you're right that they should be made in ServletWebServerFactoryConfiguration and ReactiveWebServerFactoryConfiguration. For example, the changes to apply connector customisers to the Servlet-based Tomcat factory will leave its bean method looking something like this:

@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory(
        ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers) {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.getTomcatConnectorCustomizers().addAll(
            connectorCustomizers.orderedStream().collect(Collectors.toList()));
    return factory;
}
tiwarivikash commented 5 years ago

@Ksaboor Are you still working on it?

TheCloutEngineer commented 5 years ago

Yes, I'm sorry I had to pause this week for interviews. I will continue working on it today.

mbhave commented 5 years ago

@Ksaboor Do you think you can give us an estimate on when you can submit a PR for this, please? If for some reason you aren't able to work on it by then, we can give someone else a chance.

TheCloutEngineer commented 5 years ago

yeah sure, I'm working on it right now I should have a PR by Tuesday of this week. If not I'll happily give it away to the next person. :)

TheCloutEngineer commented 5 years ago

Hey sorry but with the stress of job hunting and studying technical challenges. I'm going to have step away from this issue.

tiwarivikash commented 5 years ago

Can I work on it?

wilkinsona commented 5 years ago

@Ksaboor Thanks for letting us know. Best of luck with your job hunting.

Thanks for the offer, @tiwarivikash, but, looking back through the comments I think @Raheela1024 is next in line. @Raheela1024 are you still interested in working on this?

Raheela1024 commented 5 years ago

@wilkinsona Yes i will work on it. Thanks for this opportunity!

Razi007 commented 5 years ago

@wilkinsona I guess i raised request before @Raheela1024.But no issue @Raheela1024 please continue.

Raheela1024 commented 5 years ago

@wilkinsonaI I have changed in ServletWebServerFactoryConfiguration.java and ReactiveWebServerFactoryConfiguration.java files. Below change is for ServletWebServerFactoryConfiguration.java but i need to know am in correct direction ?. After changing that do I need to update test cases in ServletWebServerFactoryAutoConfigurationTests.java and ReactiveWebServerFactoryAutoConfigurationTests.java ?. There is any other area which I missed ?

ServletWebServerFactoryConfiguration.java

@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory(
        ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,
        ObjectProvider<TomcatContextCustomizer> contextCustomizers) {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.getTomcatConnectorCustomizers().addAll(
            connectorCustomizers.orderedStream().collect(Collectors.toList()));
    factory.getTomcatContextCustomizers().addAll(
            contextCustomizers.orderedStream().collect(Collectors.toList()));
    return factory;
}
wilkinsona commented 5 years ago

@Raheela1024 Yes, that's exactly the right direction. Thank you.

It would be good to add 4 tests that verify that connector customiser and context customiser beans are added to the reactive and servlet factories. A test that verifies that a connector customiser bean is added to the servlet factory would like something like this:

@Test
public void tomcatConnectorCustomizerBeanIsAddedToFactory() {
    WebApplicationContextRunner runner = new WebApplicationContextRunner(
            AnnotationConfigServletWebServerApplicationContext::new)
                    .withConfiguration(AutoConfigurations
                            .of(ServletWebServerFactoryAutoConfiguration.class))
                    .withUserConfiguration(
                            TomcatConnectorCustomizerConfiguration.class);
    runner.run((context) -> {
        TomcatServletWebServerFactory factory = context
                .getBean(TomcatServletWebServerFactory.class);
        assertThat(factory.getTomcatConnectorCustomizers()).hasSize(1);
    });
}

@Configuration
static class TomcatConnectorCustomizerConfiguration {

    @Bean
    public TomcatConnectorCustomizer connectorCustomizer() {
        return (connector) -> {
        };
    }

}
Raheela1024 commented 5 years ago

@wilkinsona I have created the PR Please review and let me know if missed something or doing wrongly.

wilkinsona commented 5 years ago

Awesome! Thank you very much, @Raheela1024. I'll close this issue in favour of your PR.